summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-04 04:13:11 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-04 04:13:11 +0000
commit5cccb8fa1ade2c2a45f540bf06e470a85c4ebe33 (patch)
tree83d244d9b53ef22d47ac95e351abcbaa020166ff /remoting
parentb163bc18a6ee9a7f3f0b1c90977894bbbb1c99e0 (diff)
downloadchromium_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.cc223
-rw-r--r--remoting/client/plugin/pepper_port_allocator.h45
-rw-r--r--remoting/remoting.gyp2
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',