diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-04 04:13:11 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-04 04:13:11 +0000 |
commit | 5cccb8fa1ade2c2a45f540bf06e470a85c4ebe33 (patch) | |
tree | 83d244d9b53ef22d47ac95e351abcbaa020166ff /remoting | |
parent | b163bc18a6ee9a7f3f0b1c90977894bbbb1c99e0 (diff) | |
download | chromium_src-5cccb8fa1ade2c2a45f540bf06e470a85c4ebe33.zip chromium_src-5cccb8fa1ade2c2a45f540bf06e470a85c4ebe33.tar.gz chromium_src-5cccb8fa1ade2c2a45f540bf06e470a85c4ebe33.tar.bz2 |
Implement PepperPortAllocator
The new port allocator uses pepper interfaces to make HTTP requests when
creating relay sessions.
BUG=109630
Review URL: http://codereview.chromium.org/10289007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@135293 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/client/plugin/pepper_port_allocator.cc | 223 | ||||
-rw-r--r-- | remoting/client/plugin/pepper_port_allocator.h | 45 | ||||
-rw-r--r-- | remoting/remoting.gyp | 2 |
3 files changed, 270 insertions, 0 deletions
diff --git a/remoting/client/plugin/pepper_port_allocator.cc b/remoting/client/plugin/pepper_port_allocator.cc new file mode 100644 index 0000000..e999f54 --- /dev/null +++ b/remoting/client/plugin/pepper_port_allocator.cc @@ -0,0 +1,223 @@ +// 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/client/plugin/pepper_port_allocator.h" + +#include "base/string_number_conversions.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/cpp/completion_callback.h" +#include "ppapi/cpp/url_loader.h" +#include "ppapi/cpp/url_request_info.h" +#include "ppapi/cpp/url_response_info.h" +#include "remoting/client/plugin/pepper_network_manager.h" +#include "remoting/client/plugin/pepper_packet_socket_factory.h" + +namespace remoting { + +namespace { + +// Read buffer we allocate per read when reading response from +// URLLoader. Normally the response from URL loader is smaller than 1kB. +const int kReadSize = 1024; + +class PepperPortAllocatorSession + : public cricket::HttpPortAllocatorSessionBase { + public: + PepperPortAllocatorSession( + 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 pp::InstanceHandle& instance); + virtual ~PepperPortAllocatorSession(); + + // cricket::HttpPortAllocatorBase overrides. + virtual void ConfigReady(cricket::PortConfiguration* config) OVERRIDE; + virtual void SendSessionRequest(const std::string& host, int port) OVERRIDE; + + private: + // Callback handlers for pp::URLLoader. + static void UrlLoaderOpenCallback(void* user_data, int32_t result); + static void UrlLoaderReadCallback(void* user_data, int32_t result); + + void OnUrlOpened(int32_t result); + void ReadResponseBody(); + void OnResponseBodyRead(int32_t result); + + pp::InstanceHandle instance_; + + scoped_ptr<pp::URLLoader> url_loader_; + std::vector<char> body_; + + DISALLOW_COPY_AND_ASSIGN(PepperPortAllocatorSession); +}; + +PepperPortAllocatorSession::PepperPortAllocatorSession( + 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 pp::InstanceHandle& instance) + : HttpPortAllocatorSessionBase( + allocator, channel_name, component, stun_hosts, relay_hosts, relay, ""), + instance_(instance) { +} + +PepperPortAllocatorSession::~PepperPortAllocatorSession() { +} + +void PepperPortAllocatorSession::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 PepperPortAllocatorSession::SendSessionRequest( + const std::string& host, + int port) { + url_loader_.reset(new pp::URLLoader(instance_)); + pp::URLRequestInfo request_info(instance_); + std::string url = "https://" + host + ":" + base::IntToString(port) + + GetSessionRequestUrl() + "&sn=1"; + request_info.SetURL(url); + request_info.SetMethod("GET"); + std::stringstream headers; + headers << "X-Talk-Google-Relay-Auth: " << relay_token() << "\n\r"; + headers << "X-Google-Relay-Auth: " << relay_token() << "\n\r"; + headers << "X-StreamType: " << channel_name() << "\n\r"; + request_info.SetHeaders(headers.str()); + + int result = url_loader_->Open(request_info, pp::CompletionCallback( + &PepperPortAllocatorSession::UrlLoaderOpenCallback, this)); + DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); +} + +void PepperPortAllocatorSession::OnUrlOpened(int32_t result) { + if (result == PP_ERROR_ABORTED) + return; + + if (result < 0) { + LOG(WARNING) << "URLLoader failed: " << result; + // Retry creating session. + TryCreateRelaySession(); + return; + } + + pp::URLResponseInfo response = url_loader_->GetResponseInfo(); + DCHECK(!response.is_null()); + if (response.GetStatusCode() != 200) { + LOG(WARNING) << "Received HTTP status code " << response.GetStatusCode(); + // Retry creating session. + TryCreateRelaySession(); + return; + } + + body_.clear(); + ReadResponseBody(); +} + +void PepperPortAllocatorSession::ReadResponseBody() { + int pos = body_.size(); + body_.resize(pos + kReadSize); + int result = url_loader_->ReadResponseBody( + &body_[pos], kReadSize, pp::CompletionCallback( + &PepperPortAllocatorSession::UrlLoaderReadCallback, this)); + DCHECK_EQ(result, PP_OK_COMPLETIONPENDING); +} + +void PepperPortAllocatorSession::OnResponseBodyRead(int32_t result) { + if (result == PP_ERROR_ABORTED) + return; + + if (result < 0) { + LOG(WARNING) << "Failed to read HTTP response body when " + "creating relay session: " << result; + // Retry creating session. + TryCreateRelaySession(); + return; + } + + // Resize the buffer in case we've read less than was requested. + CHECK_LE(result, kReadSize); + CHECK_GE(static_cast<int>(body_.size()), kReadSize); + body_.resize(body_.size() - kReadSize + result); + + if (result == 0) { + // Finished reading the response. + ReceiveSessionResponse(std::string(body_.begin(), body_.end())); + return; + } + + ReadResponseBody(); +} + +// static +void PepperPortAllocatorSession::UrlLoaderOpenCallback( + void* user_data, + int32_t result) { + PepperPortAllocatorSession* object = + static_cast<PepperPortAllocatorSession*>(user_data); + object->OnUrlOpened(result); +} + +// static +void PepperPortAllocatorSession::UrlLoaderReadCallback( + void* user_data, + int32_t result) { + PepperPortAllocatorSession* object = + static_cast<PepperPortAllocatorSession*>(user_data); + object->OnResponseBodyRead(result); +} + +} // namespace + +// static +scoped_ptr<PepperPortAllocator> PepperPortAllocator::Create( + const pp::InstanceHandle& instance) { + scoped_ptr<talk_base::NetworkManager> network_manager( + new PepperNetworkManager(instance)); + scoped_ptr<talk_base::PacketSocketFactory> socket_factory( + new PepperPacketSocketFactory(instance)); + scoped_ptr<PepperPortAllocator> result(new PepperPortAllocator( + instance, network_manager.Pass(), socket_factory.Pass())); + return result.Pass(); +} + +PepperPortAllocator::PepperPortAllocator( + const pp::InstanceHandle& instance, + scoped_ptr<talk_base::NetworkManager> network_manager, + scoped_ptr<talk_base::PacketSocketFactory> socket_factory) + : HttpPortAllocatorBase(network_manager.get(), socket_factory.get(), ""), + instance_(instance), + network_manager_(network_manager.Pass()), + socket_factory_(socket_factory.Pass()) { +} + +PepperPortAllocator::~PepperPortAllocator() { +} + +cricket::PortAllocatorSession* PepperPortAllocator::CreateSession( + const std::string& channel_name, + int component) { + return new PepperPortAllocatorSession( + this, channel_name, component, stun_hosts(), + relay_hosts(), relay_token(), instance_); +} + +} // namespace remoting diff --git a/remoting/client/plugin/pepper_port_allocator.h b/remoting/client/plugin/pepper_port_allocator.h new file mode 100644 index 0000000..214cea5 --- /dev/null +++ b/remoting/client/plugin/pepper_port_allocator.h @@ -0,0 +1,45 @@ +// 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_CLIENT_PLUGIN_PEPPER_PORT_ALLOCATOR_H_ +#define REMOTING_CLIENT_PLUGIN_PEPPER_PORT_ALLOCATOR_H_ + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "ppapi/cpp/instance_handle.h" +#include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h" + +namespace remoting { + +// An implementation of cricket::PortAllocator for libjingle that is +// used by the client plugin. The main difference from +// cricket::HttpPortAllocator is that it uses Pepper URLLoader API +// when creating relay sessions. +class PepperPortAllocator : public cricket::HttpPortAllocatorBase { + public: + static scoped_ptr<PepperPortAllocator> Create( + const pp::InstanceHandle& instance); + virtual ~PepperPortAllocator(); + + // cricket::HttpPortAllocatorBase overrides. + virtual cricket::PortAllocatorSession* CreateSession( + const std::string& channel_name, + int component) OVERRIDE; + + private: + PepperPortAllocator( + const pp::InstanceHandle& instance, + scoped_ptr<talk_base::NetworkManager> network_manager, + scoped_ptr<talk_base::PacketSocketFactory> socket_factory); + + pp::InstanceHandle instance_; + scoped_ptr<talk_base::NetworkManager> network_manager_; + scoped_ptr<talk_base::PacketSocketFactory> socket_factory_; + + DISALLOW_COPY_AND_ASSIGN(PepperPortAllocator); +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_PLUGIN_PEPPER_PORT_ALLOCATOR_H_ diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 37eccaf..f32d757 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -781,6 +781,8 @@ 'client/plugin/pepper_packet_socket_factory.h', 'client/plugin/pepper_plugin_thread_delegate.cc', 'client/plugin/pepper_plugin_thread_delegate.h', + 'client/plugin/pepper_port_allocator.cc', + 'client/plugin/pepper_port_allocator.h', 'client/plugin/pepper_view.cc', 'client/plugin/pepper_view.h', 'client/plugin/pepper_util.cc', |