1 // Copyright 2013 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/jingle_glue/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/jingle_glue/chromium_socket_factory.h"
15 #include "remoting/jingle_glue/network_settings.h"
22 class ChromiumPortAllocatorSession
23 : public cricket::HttpPortAllocatorSessionBase
,
24 public net::URLFetcherDelegate
{
26 ChromiumPortAllocatorSession(
27 cricket::HttpPortAllocatorBase
* allocator
,
28 const std::string
& content_name
,
30 const std::string
& ice_username_fragment
,
31 const std::string
& ice_password
,
32 const std::vector
<talk_base::SocketAddress
>& stun_hosts
,
33 const std::vector
<std::string
>& relay_hosts
,
34 const std::string
& relay
,
35 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
);
36 virtual ~ChromiumPortAllocatorSession();
38 // cricket::HttpPortAllocatorBase overrides.
39 virtual void ConfigReady(cricket::PortConfiguration
* config
) OVERRIDE
;
40 virtual void SendSessionRequest(const std::string
& host
, int port
) OVERRIDE
;
42 // net::URLFetcherDelegate interface.
43 virtual void OnURLFetchComplete(const net::URLFetcher
* url_fetcher
) OVERRIDE
;
46 scoped_refptr
<net::URLRequestContextGetter
> url_context_
;
47 std::set
<const net::URLFetcher
*> url_fetchers_
;
49 DISALLOW_COPY_AND_ASSIGN(ChromiumPortAllocatorSession
);
52 ChromiumPortAllocatorSession::ChromiumPortAllocatorSession(
53 cricket::HttpPortAllocatorBase
* allocator
,
54 const std::string
& content_name
,
56 const std::string
& ice_username_fragment
,
57 const std::string
& ice_password
,
58 const std::vector
<talk_base::SocketAddress
>& stun_hosts
,
59 const std::vector
<std::string
>& relay_hosts
,
60 const std::string
& relay
,
61 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
)
62 : HttpPortAllocatorSessionBase(allocator
,
65 ice_username_fragment
,
71 url_context_(url_context
) {}
73 ChromiumPortAllocatorSession::~ChromiumPortAllocatorSession() {
74 STLDeleteElements(&url_fetchers_
);
77 void ChromiumPortAllocatorSession::ConfigReady(
78 cricket::PortConfiguration
* config
) {
79 // Filter out non-UDP relay ports, so that we don't try using TCP.
80 for (cricket::PortConfiguration::RelayList::iterator relay
=
81 config
->relays
.begin(); relay
!= config
->relays
.end(); ++relay
) {
82 cricket::PortList filtered_ports
;
83 for (cricket::PortList::iterator port
=
84 relay
->ports
.begin(); port
!= relay
->ports
.end(); ++port
) {
85 if (port
->proto
== cricket::PROTO_UDP
) {
86 filtered_ports
.push_back(*port
);
89 relay
->ports
= filtered_ports
;
91 cricket::BasicPortAllocatorSession::ConfigReady(config
);
94 void ChromiumPortAllocatorSession::SendSessionRequest(
95 const std::string
& host
,
97 GURL
url("https://" + host
+ ":" + base::IntToString(port
) +
98 GetSessionRequestUrl() + "&sn=1");
99 scoped_ptr
<net::URLFetcher
> url_fetcher(
100 net::URLFetcher::Create(url
, net::URLFetcher::GET
, this));
101 url_fetcher
->SetRequestContext(url_context_
.get());
102 url_fetcher
->AddExtraRequestHeader("X-Talk-Google-Relay-Auth: " +
104 url_fetcher
->AddExtraRequestHeader("X-Google-Relay-Auth: " + relay_token());
105 url_fetcher
->AddExtraRequestHeader("X-Stream-Type: chromoting");
106 url_fetcher
->Start();
107 url_fetchers_
.insert(url_fetcher
.release());
110 void ChromiumPortAllocatorSession::OnURLFetchComplete(
111 const net::URLFetcher
* source
) {
112 int response_code
= source
->GetResponseCode();
113 std::string response
;
114 source
->GetResponseAsString(&response
);
116 url_fetchers_
.erase(source
);
119 if (response_code
!= net::HTTP_OK
) {
120 LOG(WARNING
) << "Received error when allocating relay session: "
122 TryCreateRelaySession();
126 ReceiveSessionResponse(response
);
132 scoped_ptr
<ChromiumPortAllocator
> ChromiumPortAllocator::Create(
133 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
,
134 const NetworkSettings
& network_settings
) {
135 scoped_ptr
<talk_base::NetworkManager
> network_manager(
136 new talk_base::BasicNetworkManager());
137 scoped_ptr
<talk_base::PacketSocketFactory
> socket_factory(
138 new remoting::ChromiumPacketSocketFactory());
139 scoped_ptr
<ChromiumPortAllocator
> result(
140 new ChromiumPortAllocator(url_context
, network_manager
.Pass(),
141 socket_factory
.Pass()));
143 // We always use PseudoTcp to provide a reliable channel. It provides poor
144 // performance when combined with TCP-based transport, so we have to disable
145 // TCP ports. ENABLE_SHARED_UFRAG flag is specified so that the same username
146 // fragment is shared between all candidates for this channel.
147 int flags
= cricket::PORTALLOCATOR_DISABLE_TCP
|
148 cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG
|
149 cricket::PORTALLOCATOR_ENABLE_IPV6
;
150 if (network_settings
.nat_traversal_mode
!=
151 NetworkSettings::NAT_TRAVERSAL_ENABLED
) {
152 flags
|= cricket::PORTALLOCATOR_DISABLE_STUN
|
153 cricket::PORTALLOCATOR_DISABLE_RELAY
;
155 result
->set_flags(flags
);
156 result
->SetPortRange(network_settings
.min_port
,
157 network_settings
.max_port
);
159 return result
.Pass();
162 ChromiumPortAllocator::ChromiumPortAllocator(
163 const scoped_refptr
<net::URLRequestContextGetter
>& url_context
,
164 scoped_ptr
<talk_base::NetworkManager
> network_manager
,
165 scoped_ptr
<talk_base::PacketSocketFactory
> socket_factory
)
166 : HttpPortAllocatorBase(network_manager
.get(),
167 socket_factory
.get(),
169 url_context_(url_context
),
170 network_manager_(network_manager
.Pass()),
171 socket_factory_(socket_factory
.Pass()) {}
173 ChromiumPortAllocator::~ChromiumPortAllocator() {
176 cricket::PortAllocatorSession
* ChromiumPortAllocator::CreateSessionInternal(
177 const std::string
& content_name
,
179 const std::string
& ice_username_fragment
,
180 const std::string
& ice_password
) {
181 return new ChromiumPortAllocatorSession(
182 this, content_name
, component
, ice_username_fragment
, ice_password
,
183 stun_hosts(), relay_hosts(), relay_token(), url_context_
);
186 } // namespace remoting