1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/protocol/chromium_port_allocator.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "net/http/http_status_code.h"
11 #include "net/url_request/url_fetcher.h"
12 #include "net/url_request/url_fetcher_delegate.h"
13 #include "net/url_request/url_request_context_getter.h"
14 #include "remoting/protocol/chromium_socket_factory.h"
15 #include "remoting/protocol/network_settings.h"
23 class ChromiumPortAllocatorSession
24 : public cricket::HttpPortAllocatorSessionBase
,
25 public net::URLFetcherDelegate
{
27 ChromiumPortAllocatorSession(
28 cricket::HttpPortAllocatorBase
* allocator
,
29 const std::string
& content_name
,
31 const std::string
& ice_username_fragment
,
32 const std::string
& ice_password
,
33 const std::vector
<talk_base::SocketAddress
>& stun_hosts
,
34 const std::vector
<std::string
>& relay_hosts
,
35 const std::string
& relay
,
36 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
);
37 virtual ~ChromiumPortAllocatorSession();
39 // cricket::HttpPortAllocatorBase overrides.
40 virtual void ConfigReady(cricket::PortConfiguration
* config
) OVERRIDE
;
41 virtual void SendSessionRequest(const std::string
& host
, int port
) OVERRIDE
;
43 // net::URLFetcherDelegate interface.
44 virtual void OnURLFetchComplete(const net::URLFetcher
* url_fetcher
) OVERRIDE
;
47 scoped_refptr
<net::URLRequestContextGetter
> url_context_
;
48 std::set
<const net::URLFetcher
*> url_fetchers_
;
50 DISALLOW_COPY_AND_ASSIGN(ChromiumPortAllocatorSession
);
53 ChromiumPortAllocatorSession::ChromiumPortAllocatorSession(
54 cricket::HttpPortAllocatorBase
* allocator
,
55 const std::string
& content_name
,
57 const std::string
& ice_username_fragment
,
58 const std::string
& ice_password
,
59 const std::vector
<talk_base::SocketAddress
>& stun_hosts
,
60 const std::vector
<std::string
>& relay_hosts
,
61 const std::string
& relay
,
62 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
)
63 : HttpPortAllocatorSessionBase(allocator
,
66 ice_username_fragment
,
72 url_context_(url_context
) {}
74 ChromiumPortAllocatorSession::~ChromiumPortAllocatorSession() {
75 STLDeleteElements(&url_fetchers_
);
78 void ChromiumPortAllocatorSession::ConfigReady(
79 cricket::PortConfiguration
* config
) {
80 // Filter out non-UDP relay ports, so that we don't try using TCP.
81 for (cricket::PortConfiguration::RelayList::iterator relay
=
82 config
->relays
.begin(); relay
!= config
->relays
.end(); ++relay
) {
83 cricket::PortList filtered_ports
;
84 for (cricket::PortList::iterator port
=
85 relay
->ports
.begin(); port
!= relay
->ports
.end(); ++port
) {
86 if (port
->proto
== cricket::PROTO_UDP
) {
87 filtered_ports
.push_back(*port
);
90 relay
->ports
= filtered_ports
;
92 cricket::BasicPortAllocatorSession::ConfigReady(config
);
95 void ChromiumPortAllocatorSession::SendSessionRequest(
96 const std::string
& host
,
98 GURL
url("https://" + host
+ ":" + base::IntToString(port
) +
99 GetSessionRequestUrl() + "&sn=1");
100 scoped_ptr
<net::URLFetcher
> url_fetcher(
101 net::URLFetcher::Create(url
, net::URLFetcher::GET
, this));
102 url_fetcher
->SetRequestContext(url_context_
.get());
103 url_fetcher
->AddExtraRequestHeader("X-Talk-Google-Relay-Auth: " +
105 url_fetcher
->AddExtraRequestHeader("X-Google-Relay-Auth: " + relay_token());
106 url_fetcher
->AddExtraRequestHeader("X-Stream-Type: chromoting");
107 url_fetcher
->Start();
108 url_fetchers_
.insert(url_fetcher
.release());
111 void ChromiumPortAllocatorSession::OnURLFetchComplete(
112 const net::URLFetcher
* source
) {
113 int response_code
= source
->GetResponseCode();
114 std::string response
;
115 source
->GetResponseAsString(&response
);
117 url_fetchers_
.erase(source
);
120 if (response_code
!= net::HTTP_OK
) {
121 LOG(WARNING
) << "Received error when allocating relay session: "
123 TryCreateRelaySession();
127 ReceiveSessionResponse(response
);
133 scoped_ptr
<ChromiumPortAllocator
> ChromiumPortAllocator::Create(
134 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
,
135 const NetworkSettings
& network_settings
) {
136 scoped_ptr
<talk_base::NetworkManager
> network_manager(
137 new talk_base::BasicNetworkManager());
138 scoped_ptr
<talk_base::PacketSocketFactory
> socket_factory(
139 new ChromiumPacketSocketFactory());
140 scoped_ptr
<ChromiumPortAllocator
> result(
141 new ChromiumPortAllocator(url_context
, network_manager
.Pass(),
142 socket_factory
.Pass()));
144 // We always use PseudoTcp to provide a reliable channel. It provides poor
145 // performance when combined with TCP-based transport, so we have to disable
146 // TCP ports. ENABLE_SHARED_UFRAG flag is specified so that the same username
147 // fragment is shared between all candidates for this channel.
148 int flags
= cricket::PORTALLOCATOR_DISABLE_TCP
|
149 cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG
|
150 cricket::PORTALLOCATOR_ENABLE_IPV6
;
152 if (!(network_settings
.flags
& NetworkSettings::NAT_TRAVERSAL_STUN
))
153 flags
|= cricket::PORTALLOCATOR_DISABLE_STUN
;
155 if (!(network_settings
.flags
& NetworkSettings::NAT_TRAVERSAL_RELAY
))
156 flags
|= cricket::PORTALLOCATOR_DISABLE_RELAY
;
158 result
->set_flags(flags
);
159 result
->SetPortRange(network_settings
.min_port
,
160 network_settings
.max_port
);
162 return result
.Pass();
165 ChromiumPortAllocator::ChromiumPortAllocator(
166 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
,
167 scoped_ptr
<talk_base::NetworkManager
> network_manager
,
168 scoped_ptr
<talk_base::PacketSocketFactory
> socket_factory
)
169 : HttpPortAllocatorBase(network_manager
.get(),
170 socket_factory
.get(),
172 url_context_(url_context
),
173 network_manager_(network_manager
.Pass()),
174 socket_factory_(socket_factory
.Pass()) {}
176 ChromiumPortAllocator::~ChromiumPortAllocator() {
179 cricket::PortAllocatorSession
* ChromiumPortAllocator::CreateSessionInternal(
180 const std::string
& content_name
,
182 const std::string
& ice_username_fragment
,
183 const std::string
& ice_password
) {
184 return new ChromiumPortAllocatorSession(
185 this, content_name
, component
, ice_username_fragment
, ice_password
,
186 stun_hosts(), relay_hosts(), relay_token(), url_context_
);
189 } // namespace protocol
190 } // namespace remoting