Commit 95178556 authored by sergeyu@chromium.org's avatar sergeyu@chromium.org

Implement HostPortAllocator.

HostPortAllocator is a PortAllocator specific to Chromoting host.

BUG=103991

Review URL: https://chromiumcodereview.appspot.com/10160013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134650 0039d316-1c4b-4281-b951-d872f2087c98
parent 57a9cbcb
......@@ -17,6 +17,7 @@
#include "remoting/host/desktop_environment.h"
#include "remoting/host/event_executor.h"
#include "remoting/host/host_config.h"
#include "remoting/host/host_port_allocator.h"
#include "remoting/host/screen_recorder.h"
#include "remoting/protocol/connection_to_client.h"
#include "remoting/protocol/client_stub.h"
......@@ -25,9 +26,6 @@
#include "remoting/protocol/jingle_session_manager.h"
#include "remoting/protocol/libjingle_transport_factory.h"
#include "remoting/protocol/session_config.h"
#include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h"
#include "third_party/libjingle/source/talk/base/network.h"
#include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h"
using remoting::protocol::ConnectionToClient;
using remoting::protocol::InputStub;
......@@ -100,38 +98,18 @@ void ChromotingHost::Start() {
return;
state_ = kStarted;
// Create port allocator.
// TODO(sergeyu): Replace the code below with HostPortAllocator when
// it is implemented.
scoped_ptr<talk_base::NetworkManager> network_manager(
new talk_base::BasicNetworkManager());
scoped_ptr<talk_base::PacketSocketFactory> socket_factory(
new talk_base::BasicPacketSocketFactory());
scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator(
new cricket::HttpPortAllocator(
network_manager.get(), socket_factory.get(), ""));
// We always use PseudoTcp to provide a reliable channel. It
// provides poor performance when combined with TCP-based transport,
// so we have to disable TCP ports.
int port_allocator_flags = cricket::PORTALLOCATOR_DISABLE_TCP;
if (network_settings_.nat_traversal_mode !=
NetworkSettings::NAT_TRAVERSAL_ENABLED) {
port_allocator_flags |= cricket::PORTALLOCATOR_DISABLE_STUN |
cricket::PORTALLOCATOR_DISABLE_RELAY;
}
port_allocator->set_flags(port_allocator_flags);
port_allocator->SetPortRange(network_settings_.min_port,
network_settings_.max_port);
// Create port allocator and transport factory.
scoped_ptr<HostPortAllocator> port_allocator(
HostPortAllocator::Create(context_->url_request_context_getter(),
network_settings_));
bool incoming_only = network_settings_.nat_traversal_mode ==
NetworkSettings::NAT_TRAVERSAL_DISABLED;
scoped_ptr<protocol::TransportFactory> transport_factory(
new protocol::LibjingleTransportFactory(
network_manager.Pass(), socket_factory.Pass(),
port_allocator.Pass(), incoming_only));
port_allocator.PassAs<cricket::HttpPortAllocatorBase>(),
incoming_only));
// Create and start session manager.
bool fetch_stun_relay_info = network_settings_.nat_traversal_mode ==
......
......@@ -18,6 +18,7 @@
#include "remoting/host/desktop_environment.h"
#include "remoting/host/host_key_pair.h"
#include "remoting/host/host_status_observer.h"
#include "remoting/host/network_settings.h"
#include "remoting/host/ui_strings.h"
#include "remoting/jingle_glue/jingle_thread.h"
#include "remoting/jingle_glue/signal_strategy.h"
......@@ -39,49 +40,6 @@ class DesktopEnvironment;
class Encoder;
class ScreenRecorder;
struct NetworkSettings {
enum NatTraversalMode {
// Don't use STUN or relay servers. Accept incoming P2P connection
// attempts, but don't initiate any. This ensures that the peer is
// on the same network. Note that connection will always fail if
// both ends use this mode.
NAT_TRAVERSAL_DISABLED,
// Don't use STUN or relay servers but make outgoing connections.
NAT_TRAVERSAL_OUTGOING,
// Active NAT traversal using STUN and relay servers.
NAT_TRAVERSAL_ENABLED,
};
NetworkSettings()
: nat_traversal_mode(NAT_TRAVERSAL_DISABLED),
min_port(0),
max_port(0) {
}
explicit NetworkSettings(bool allow_nat_traversal)
: nat_traversal_mode(allow_nat_traversal ?
NAT_TRAVERSAL_ENABLED :
NAT_TRAVERSAL_DISABLED),
min_port(0),
max_port(0) {
}
explicit NetworkSettings(NatTraversalMode nat_traversal_mode)
: nat_traversal_mode(nat_traversal_mode),
min_port(0),
max_port(0) {
}
NatTraversalMode nat_traversal_mode;
// |min_port| and |max_port| specify range (inclusive) of ports used by
// P2P sessions. Any port can be used when both values are set to 0.
int min_port;
int max_port;
};
// A class to implement the functionality of a host process.
//
// Here's the work flow of this class:
......
......@@ -75,7 +75,7 @@ base::MessageLoopProxy* ChromotingHostContext::file_message_loop() {
return file_thread_.message_loop_proxy();
}
const scoped_refptr<URLRequestContextGetter>&
const scoped_refptr<net::URLRequestContextGetter>&
ChromotingHostContext::url_request_context_getter() {
DCHECK(url_request_context_getter_.get());
return url_request_context_getter_;
......
......@@ -12,9 +12,11 @@
#include "base/threading/thread.h"
#include "remoting/jingle_glue/jingle_thread.h"
namespace remoting {
namespace net {
class URLRequestContextGetter;
} // namespace net
namespace remoting {
// A class that manages threads and running context for the chromoting host
// process. This class is virtual only for testing purposes (see below).
......@@ -40,7 +42,8 @@ class ChromotingHostContext {
virtual base::MessageLoopProxy* ui_message_loop();
virtual base::MessageLoopProxy* io_message_loop();
virtual base::MessageLoopProxy* file_message_loop();
const scoped_refptr<URLRequestContextGetter>& url_request_context_getter();
const scoped_refptr<net::URLRequestContextGetter>&
url_request_context_getter();
private:
FRIEND_TEST_ALL_PREFIXES(ChromotingHostContextTest, StartAndStop);
......@@ -67,7 +70,7 @@ class ChromotingHostContext {
scoped_refptr<base::MessageLoopProxy> ui_message_loop_;
scoped_refptr<URLRequestContextGetter> url_request_context_getter_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
DISALLOW_COPY_AND_ASSIGN(ChromotingHostContext);
};
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/host_port_allocator.h"
#include "base/bind.h"
#include "base/stl_util.h"
#include "base/string_number_conversions.h"
#include "googleurl/src/gurl.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_request_context_getter.h"
#include "remoting/host/network_settings.h"
#include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h"
namespace remoting {
namespace {
class HostPortAllocatorSession
: public cricket::HttpPortAllocatorSessionBase {
public:
HostPortAllocatorSession(
cricket::HttpPortAllocatorBase* allocator,
const std::string& channel_name,
int component,
const std::vector<talk_base::SocketAddress>& stun_hosts,
const std::vector<std::string>& relay_hosts,
const std::string& relay,
const scoped_refptr<net::URLRequestContextGetter>& url_context);
virtual ~HostPortAllocatorSession();
// cricket::HttpPortAllocatorBase overrides.
virtual void ConfigReady(cricket::PortConfiguration* config) OVERRIDE;
virtual void SendSessionRequest(const std::string& host, int port) OVERRIDE;
private:
void OnSessionRequestDone(UrlFetcher* url_fetcher,
const net::URLRequestStatus& status,
int response_code,
const std::string& response);
scoped_refptr<net::URLRequestContextGetter> url_context_;
std::set<UrlFetcher*> url_fetchers_;
DISALLOW_COPY_AND_ASSIGN(HostPortAllocatorSession);
};
HostPortAllocatorSession::HostPortAllocatorSession(
cricket::HttpPortAllocatorBase* allocator,
const std::string& channel_name,
int component,
const std::vector<talk_base::SocketAddress>& stun_hosts,
const std::vector<std::string>& relay_hosts,
const std::string& relay,
const scoped_refptr<net::URLRequestContextGetter>& url_context)
: HttpPortAllocatorSessionBase(
allocator, channel_name, component, stun_hosts, relay_hosts, relay, ""),
url_context_(url_context) {
}
HostPortAllocatorSession::~HostPortAllocatorSession() {
STLDeleteElements(&url_fetchers_);
}
void HostPortAllocatorSession::ConfigReady(cricket::PortConfiguration* config) {
// Filter out non-UDP relay ports, so that we don't try using TCP.
for (cricket::PortConfiguration::RelayList::iterator relay =
config->relays.begin(); relay != config->relays.end(); ++relay) {
cricket::PortConfiguration::PortList filtered_ports;
for (cricket::PortConfiguration::PortList::iterator port =
relay->ports.begin(); port != relay->ports.end(); ++port) {
if (port->proto == cricket::PROTO_UDP) {
filtered_ports.push_back(*port);
}
}
relay->ports = filtered_ports;
}
cricket::BasicPortAllocatorSession::ConfigReady(config);
}
void HostPortAllocatorSession::SendSessionRequest(const std::string& host,
int port) {
GURL url("https://" + host + ":" + base::IntToString(port) +
GetSessionRequestUrl() + "&sn=1");
scoped_ptr<UrlFetcher> url_fetcher(new UrlFetcher(url, UrlFetcher::GET));
url_fetcher->SetRequestContext(url_context_);
url_fetcher->SetHeader("X-Talk-Google-Relay-Auth", relay_token());
url_fetcher->SetHeader("X-Google-Relay-Auth", relay_token());
url_fetcher->SetHeader("X-Stream-Type", channel_name());
url_fetcher->Start(base::Bind(&HostPortAllocatorSession::OnSessionRequestDone,
base::Unretained(this), url_fetcher.get()));
url_fetchers_.insert(url_fetcher.release());
}
void HostPortAllocatorSession::OnSessionRequestDone(
UrlFetcher* url_fetcher,
const net::URLRequestStatus& status,
int response_code,
const std::string& response) {
url_fetchers_.erase(url_fetcher);
delete url_fetcher;
if (response_code != net::HTTP_OK) {
LOG(WARNING) << "Received error when allocating relay session: "
<< response_code;
TryCreateRelaySession();
return;
}
ReceiveSessionResponse(response);
}
} // namespace
// static
scoped_ptr<HostPortAllocator> HostPortAllocator::Create(
const scoped_refptr<net::URLRequestContextGetter>& url_context,
const NetworkSettings& network_settings) {
scoped_ptr<talk_base::NetworkManager> network_manager(
new talk_base::BasicNetworkManager());
scoped_ptr<talk_base::PacketSocketFactory> socket_factory(
new talk_base::BasicPacketSocketFactory());
scoped_ptr<HostPortAllocator> result(
new HostPortAllocator(url_context, network_manager.Pass(),
socket_factory.Pass()));
// We always use PseudoTcp to provide a reliable channel. It
// provides poor performance when combined with TCP-based transport,
// so we have to disable TCP ports.
int flags = cricket::PORTALLOCATOR_DISABLE_TCP;
if (network_settings.nat_traversal_mode !=
NetworkSettings::NAT_TRAVERSAL_ENABLED) {
flags |= cricket::PORTALLOCATOR_DISABLE_STUN |
cricket::PORTALLOCATOR_DISABLE_RELAY;
}
result->set_flags(flags);
result->SetPortRange(network_settings.min_port,
network_settings.max_port);
return result.Pass();
}
HostPortAllocator::HostPortAllocator(
const scoped_refptr<net::URLRequestContextGetter>& url_context,
scoped_ptr<talk_base::NetworkManager> network_manager,
scoped_ptr<talk_base::PacketSocketFactory> socket_factory)
: HttpPortAllocatorBase(network_manager.get(), socket_factory.get(), ""),
url_context_(url_context),
network_manager_(network_manager.Pass()),
socket_factory_(socket_factory.Pass()) {
}
HostPortAllocator::~HostPortAllocator() {
}
cricket::PortAllocatorSession* HostPortAllocator::CreateSession(
const std::string& channel_name,
int component) {
return new HostPortAllocatorSession(
this, channel_name, component, stun_hosts(),
relay_hosts(), relay_token(), url_context_);
}
} // namespace remoting
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_HOST_HOST_PORT_ALLOCATOR_H_
#define REMOTING_HOST_HOST_PORT_ALLOCATOR_H_
#include <set>
#include "base/memory/scoped_ptr.h"
#include "remoting/host/url_fetcher.h"
#include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h"
namespace net {
class URLRequestContextGetter;
} // namespace net
namespace remoting {
struct NetworkSettings;
// An implementation of cricket::PortAllocator for libjingle that is
// used by the remoting host. The main difference from
// cricket::HttpPortAllocator is that it uses Chromium's HTTP stack
// when creating relay sessions. It also configures itself according
// to the specified NetworkSettings.
class HostPortAllocator : public cricket::HttpPortAllocatorBase {
public:
static scoped_ptr<HostPortAllocator> Create(
const scoped_refptr<net::URLRequestContextGetter>& url_context,
const NetworkSettings& network_settings);
virtual ~HostPortAllocator();
// cricket::HttpPortAllocatorBase overrides.
virtual cricket::PortAllocatorSession* CreateSession(
const std::string& channel_name,
int component) OVERRIDE;
private:
HostPortAllocator(
const scoped_refptr<net::URLRequestContextGetter>& url_context,
scoped_ptr<talk_base::NetworkManager> network_manager,
scoped_ptr<talk_base::PacketSocketFactory> socket_factory);
scoped_refptr<net::URLRequestContextGetter> url_context_;
scoped_ptr<talk_base::NetworkManager> network_manager_;
scoped_ptr<talk_base::PacketSocketFactory> socket_factory_;
DISALLOW_COPY_AND_ASSIGN(HostPortAllocator);
};
} // namespace remoting
#endif // REMOTING_HOST_HOST_PORT_ALLOCATOR_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_HOST_NETWORK_SETTINGS_H_
#define REMOTING_HOST_NETWORK_SETTINGS_H_
namespace remoting {
struct NetworkSettings {
enum NatTraversalMode {
// Active NAT traversal using STUN and relay servers.
NAT_TRAVERSAL_ENABLED,
// Don't use STUN or relay servers. Accept incoming P2P connection
// attempts, but don't initiate any. This ensures that the peer is
// on the same network. Note that connection will always fail if
// both ends use this mode.
NAT_TRAVERSAL_DISABLED,
// Don't use STUN or relay servers but make outgoing connections.
NAT_TRAVERSAL_OUTGOING,
};
NetworkSettings()
: nat_traversal_mode(NAT_TRAVERSAL_DISABLED),
min_port(0),
max_port(0) {
}
explicit NetworkSettings(NatTraversalMode nat_traversal_mode)
: nat_traversal_mode(nat_traversal_mode),
min_port(0),
max_port(0) {
}
NatTraversalMode nat_traversal_mode;
// |min_port| and |max_port| specify range (inclusive) of ports used by
// P2P sessions. Any port can be used when both values are set to 0.
int min_port;
int max_port;
};
} // namespace remoting
#endif // REMOTING_HOST_NETWORK_SETTINGS_H_
......@@ -551,7 +551,9 @@ void HostNPScriptObject::FinishConnectNetworkThread(
LOG(INFO) << "NAT state: " << nat_traversal_enabled_;
host_ = new ChromotingHost(
host_context_.get(), signal_strategy_.get(), desktop_environment_.get(),
NetworkSettings(nat_traversal_enabled_));
NetworkSettings(nat_traversal_enabled_ ?
NetworkSettings::NAT_TRAVERSAL_ENABLED :
NetworkSettings::NAT_TRAVERSAL_DISABLED));
host_->AddStatusObserver(this);
log_to_server_.reset(
new LogToServer(host_, ServerLogEntry::IT2ME, signal_strategy_.get()));
......
......@@ -346,7 +346,10 @@ class HostProcess
DesktopEnvironment::CreateForService(context_.get());
}
NetworkSettings network_settings(allow_nat_traversal_);
NetworkSettings network_settings(
allow_nat_traversal_ ?
NetworkSettings::NAT_TRAVERSAL_ENABLED :
NetworkSettings::NAT_TRAVERSAL_DISABLED);
if (!allow_nat_traversal_) {
network_settings.min_port = kMinPortNumber;
network_settings.max_port = kMaxPortNumber;
......
......@@ -50,7 +50,7 @@ SignalingConnector::~SignalingConnector() {
void SignalingConnector::EnableOAuth(
scoped_ptr<OAuthCredentials> oauth_credentials,
const base::Closure& oauth_failed_callback,
URLRequestContextGetter* url_context) {
net::URLRequestContextGetter* url_context) {
oauth_credentials_ = oauth_credentials.Pass();
oauth_failed_callback_ = oauth_failed_callback;
gaia_oauth_client_.reset(new GaiaOAuthClient(kGaiaOAuth2Url, url_context));
......
......@@ -13,9 +13,11 @@
#include "remoting/host/gaia_oauth_client.h"
#include "remoting/jingle_glue/xmpp_signal_strategy.h"
namespace remoting {
namespace net {
class URLRequestContextGetter;
} // namespace net
namespace remoting {
// SignalingConnector listens for SignalStrategy status notifications
// and attempts to keep it connected when possible. When signalling is
......@@ -55,7 +57,7 @@ class SignalingConnector
void EnableOAuth(scoped_ptr<OAuthCredentials> oauth_credentials,
const base::Closure& oauth_failed_callback,
URLRequestContextGetter* url_context);
net::URLRequestContextGetter* url_context);
// SignalStrategy::Listener interface.
virtual void OnSignalStrategyStateChange(
......
......@@ -24,6 +24,7 @@ class UrlFetcher::Core : public base::RefCountedThreadSafe<Core>,
net::URLRequestContextGetter* request_context_getter);
void SetUploadData(const std::string& upload_content_type,
const std::string& upload_content);
void SetHeader(const std::string& key, const std::string& value);
void Start(const UrlFetcher::DoneCallback& done_callback);
void Detach();
......@@ -57,6 +58,8 @@ class UrlFetcher::Core : public base::RefCountedThreadSafe<Core>,
std::string upload_content_;
std::string upload_content_type_;
net::HttpRequestHeaders request_headers_;
scoped_ptr<net::URLRequest> request_;
scoped_refptr<net::IOBuffer> buffer_;
......@@ -89,6 +92,11 @@ void UrlFetcher::Core::SetUploadData(const std::string& upload_content_type,
upload_content_ = upload_content;
}
void UrlFetcher::Core::SetHeader(const std::string& key,
const std::string& value) {
request_headers_.SetHeader(key, value);
}
void UrlFetcher::Core::Start(const UrlFetcher::DoneCallback& done_callback) {
done_callback_ = done_callback;
io_message_loop_ = request_context_getter_->GetIOMessageLoopProxy();
......@@ -146,16 +154,16 @@ void UrlFetcher::Core::DoStart() {
DCHECK(!upload_content_type_.empty());
request_->set_method("POST");
net::HttpRequestHeaders headers;
headers.SetHeader(net::HttpRequestHeaders::kContentType,
upload_content_type_);
request_->SetExtraRequestHeaders(headers);
request_headers_.SetHeader(net::HttpRequestHeaders::kContentType,
upload_content_type_);
request_->AppendBytesToUpload(
upload_content_.data(), static_cast<int>(upload_content_.length()));
break;
}
request_->SetExtraRequestHeaders(request_headers_);
request_->Start();
}
......@@ -200,6 +208,10 @@ void UrlFetcher::SetUploadData(const std::string& upload_content_type,
core_->SetUploadData(upload_content_type, upload_content);
}
void UrlFetcher::SetHeader(const std::string& key, const std::string& value) {
core_->SetHeader(key, value);
}
void UrlFetcher::Start(const DoneCallback& done_callback) {
core_->Start(done_callback);
}
......
......@@ -47,6 +47,7 @@ class UrlFetcher {
net::URLRequestContextGetter* request_context_getter);
void SetUploadData(const std::string& upload_content_type,
const std::string& upload_content);
void SetHeader(const std::string& key, const std::string& value);
void Start(const DoneCallback& done_callback);
private:
......
......@@ -289,13 +289,9 @@ void LibjingleStreamTransport::NotifyConnectFailed() {
} // namespace
LibjingleTransportFactory::LibjingleTransportFactory(
scoped_ptr<talk_base::NetworkManager> network_manager,
scoped_ptr<talk_base::PacketSocketFactory> socket_factory,
scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator,
bool incoming_only)
: network_manager_(network_manager.Pass()),
socket_factory_(socket_factory.Pass()),
http_port_allocator_(port_allocator.get()),
: http_port_allocator_(port_allocator.get()),
port_allocator_(port_allocator.Pass()),
incoming_only_(incoming_only) {
}
......
......@@ -22,9 +22,11 @@ namespace protocol {
class LibjingleTransportFactory : public TransportFactory {
public:
// Need to use cricket::HttpPortAllocatorBase pointer for the
// |port_allocator|, so that it is possible to configure
// |port_allocator| with STUN/Relay addresses.
// TODO(sergeyu): Reconsider this design.
LibjingleTransportFactory(
scoped_ptr<talk_base::NetworkManager> network_manager,
scoped_ptr<talk_base::PacketSocketFactory> socket_factory,
scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator,
bool incoming_only);
......
......@@ -999,6 +999,8 @@
'host/host_config.h',
'host/host_key_pair.cc',
'host/host_key_pair.h',
'host/host_port_allocator.cc',
'host/host_port_allocator.h',
'host/host_secret.cc',
'host/host_secret.h',
'host/host_status_observer.h',
......@@ -1016,6 +1018,7 @@
'host/local_input_monitor_win.cc',
'host/log_to_server.cc',
'host/log_to_server.h',
'host/network_settings.h',
'host/policy_hack/nat_policy.h',
'host/policy_hack/nat_policy.cc',
'host/policy_hack/nat_policy_linux.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment