summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 22:16:02 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 22:16:02 +0000
commit6d3ad505c8e8173e98045d845a910f77fab9ffcf (patch)
treee996bba53b108dabdcb9b0af89eab2e4664a0bf5 /content
parentb0f146ff51b2b37a2e3549c875fb42365ded7a21 (diff)
downloadchromium_src-6d3ad505c8e8173e98045d845a910f77fab9ffcf.zip
chromium_src-6d3ad505c8e8173e98045d845a910f77fab9ffcf.tar.gz
chromium_src-6d3ad505c8e8173e98045d845a910f77fab9ffcf.tar.bz2
Relay server support for P2P Transport API.
BUG=41776 TEST=None Review URL: http://codereview.chromium.org/7791008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101396 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/renderer/p2p/p2p_transport_impl.cc6
-rw-r--r--content/renderer/p2p/p2p_transport_impl.h3
-rw-r--r--content/renderer/p2p/p2p_transport_impl_unittest.cc4
-rw-r--r--content/renderer/p2p/port_allocator.cc198
-rw-r--r--content/renderer/p2p/port_allocator.h43
5 files changed, 240 insertions, 14 deletions
diff --git a/content/renderer/p2p/p2p_transport_impl.cc b/content/renderer/p2p/p2p_transport_impl.cc
index 29266e2..ada21a5 100644
--- a/content/renderer/p2p/p2p_transport_impl.cc
+++ b/content/renderer/p2p/p2p_transport_impl.cc
@@ -44,7 +44,8 @@ P2PTransportImpl::P2PTransportImpl(P2PSocketDispatcher* socket_dispatcher)
P2PTransportImpl::~P2PTransportImpl() {
}
-bool P2PTransportImpl::Init(const std::string& name,
+bool P2PTransportImpl::Init(WebKit::WebFrame* web_frame,
+ const std::string& name,
Protocol protocol,
const Config& config,
EventHandler* event_handler) {
@@ -58,8 +59,9 @@ bool P2PTransportImpl::Init(const std::string& name,
event_handler_ = event_handler;
if (socket_dispatcher_) {
+ DCHECK(web_frame);
allocator_.reset(new P2PPortAllocator(
- socket_dispatcher_, network_manager_.get(),
+ web_frame, socket_dispatcher_, network_manager_.get(),
socket_factory_.get(), config));
} else {
// Use BasicPortAllocator if we don't have P2PSocketDispatcher
diff --git a/content/renderer/p2p/p2p_transport_impl.h b/content/renderer/p2p/p2p_transport_impl.h
index d5d9e81..82072b1 100644
--- a/content/renderer/p2p/p2p_transport_impl.h
+++ b/content/renderer/p2p/p2p_transport_impl.h
@@ -53,7 +53,8 @@ class P2PTransportImpl : public webkit_glue::P2PTransport,
virtual ~P2PTransportImpl();
// webkit_glue::P2PTransport interface.
- virtual bool Init(const std::string& name,
+ virtual bool Init(WebKit::WebFrame* web_frame,
+ const std::string& name,
Protocol protocol,
const Config& config,
EventHandler* event_handler) OVERRIDE;
diff --git a/content/renderer/p2p/p2p_transport_impl_unittest.cc b/content/renderer/p2p/p2p_transport_impl_unittest.cc
index bf6f8d9..83c23e5 100644
--- a/content/renderer/p2p/p2p_transport_impl_unittest.cc
+++ b/content/renderer/p2p/p2p_transport_impl_unittest.cc
@@ -353,9 +353,9 @@ class P2PTransportImplTest : public testing::Test {
void Init(P2PTransport::Protocol protocol) {
P2PTransport::Config config;
ASSERT_TRUE(transport1_->Init(
- kTransportName1, protocol, config, &event_handler1_));
+ NULL, kTransportName1, protocol, config, &event_handler1_));
ASSERT_TRUE(transport2_->Init(
- kTransportName2, protocol, config, &event_handler2_));
+ NULL, kTransportName2, protocol, config, &event_handler2_));
}
MessageLoop message_loop_;
diff --git a/content/renderer/p2p/port_allocator.cc b/content/renderer/p2p/port_allocator.cc
index 55f502a..42df275 100644
--- a/content/renderer/p2p/port_allocator.cc
+++ b/content/renderer/p2p/port_allocator.cc
@@ -5,18 +5,58 @@
#include "content/renderer/p2p/port_allocator.h"
#include "base/bind.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "base/string_util.h"
#include "content/renderer/p2p/host_address_request.h"
#include "jingle/glue/utils.h"
#include "net/base/ip_endpoint.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLError.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderOptions.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h"
+
+using WebKit::WebString;
+using WebKit::WebURL;
+using WebKit::WebURLLoader;
+using WebKit::WebURLLoaderOptions;
+using WebKit::WebURLRequest;
+using WebKit::WebURLResponse;
namespace content {
+namespace {
+
+// URL used to create a relay session.
+const char kCreateRelaySessionURL[] = "/create_session";
+
+// Number of times we will try to request relay session.
+const int kRelaySessionRetries = 3;
+
+// Manimum relay server size we would try to parse.
+const int kMaximumRelayResponseSize = 102400;
+
+bool ParsePortNumber(
+ const std::string& string, int* value) {
+ if (!base::StringToInt(string, value) || *value <= 0 || *value >= 65536) {
+ LOG(ERROR) << "Received invalid port number from relay server: " << string;
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
P2PPortAllocator::P2PPortAllocator(
+ WebKit::WebFrame* web_frame,
P2PSocketDispatcher* socket_dispatcher,
talk_base::NetworkManager* network_manager,
talk_base::PacketSocketFactory* socket_factory,
const webkit_glue::P2PTransport::Config& config)
: cricket::BasicPortAllocator(network_manager, socket_factory),
+ web_frame_(web_frame),
socket_dispatcher_(socket_dispatcher),
config_(config) {
}
@@ -43,15 +83,43 @@ P2PPortAllocatorSession::~P2PPortAllocatorSession() {
stun_address_request_->Cancel();
}
+void P2PPortAllocatorSession::didReceiveData(
+ WebURLLoader* loader, const char* data,
+ int data_length, int encoded_data_length) {
+ DCHECK_EQ(loader, relay_session_request_.get());
+ if (static_cast<int>(relay_session_response_.size()) + data_length >
+ kMaximumRelayResponseSize) {
+ LOG(ERROR) << "Response received from the server is too big.";
+ loader->cancel();
+ return;
+ }
+ relay_session_response_.append(data, data + data_length);
+}
+
+void P2PPortAllocatorSession::didFinishLoading(WebURLLoader* loader,
+ double finish_time) {
+ ParseRelayResponse();
+}
+
+void P2PPortAllocatorSession::didFail(WebKit::WebURLLoader* loader,
+ const WebKit::WebURLError& error) {
+ DCHECK_EQ(loader, relay_session_request_.get());
+ DCHECK_NE(error.reason, 0);
+
+ LOG(ERROR) << "Relay session request failed.";
+
+ // Retry the request.
+ AllocateRelaySession();
+}
+
void P2PPortAllocatorSession::GetPortConfigurations() {
- // Add am empty configuration synchronously, so a local connection
+ // Add an empty configuration synchronously, so a local connection
// can be started immediately.
ConfigReady(new cricket::PortConfiguration(
talk_base::SocketAddress(), "", "", ""));
ResolveStunServerAddress();
-
- // TODO(sergeyu): Implement relay server support.
+ AllocateRelaySession();
}
void P2PPortAllocatorSession::ResolveStunServerAddress() {
@@ -74,14 +142,132 @@ void P2PPortAllocatorSession::OnStunServerAddress(
return;
}
- talk_base::SocketAddress socket_address;
if (!jingle_glue::IPEndPointToSocketAddress(
net::IPEndPoint(address, allocator_->config_.stun_server_port),
- &socket_address)) {
+ &stun_server_address_)) {
return;
}
- ConfigReady(new cricket::PortConfiguration(socket_address, "", "", ""));
+ AddConfig();
+}
+
+void P2PPortAllocatorSession::AllocateRelaySession() {
+ if (allocator_->config_.relay_server.empty())
+ return;
+
+ if (!allocator_->config_.legacy_relay) {
+ NOTIMPLEMENTED() << " TURN support is not implemented yet.";
+ return;
+ }
+
+ if (relay_session_attemtps_ > kRelaySessionRetries)
+ return;
+ relay_session_attemtps_++;
+
+ relay_session_response_.clear();
+
+ WebURLLoaderOptions options;
+ options.allowCredentials = false;
+ options.crossOriginRequestPolicy =
+ WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
+ relay_session_request_.reset(
+ allocator_->web_frame_->createAssociatedURLLoader(options));
+ if (!relay_session_request_.get()) {
+ LOG(ERROR) << "Failed to create URL loader.";
+ return;
+ }
+
+ WebURLRequest request;
+ request.initialize();
+ request.setURL(WebURL(GURL(
+ "http://" + allocator_->config_.relay_server + kCreateRelaySessionURL)));
+ request.setAllowStoredCredentials(false);
+ request.setCachePolicy(WebURLRequest::ReloadIgnoringCacheData);
+ request.setHTTPMethod("GET");
+ request.addHTTPHeaderField(
+ WebString::fromUTF8("X-Talk-Google-Relay-Auth"),
+ WebString::fromUTF8(allocator_->config_.relay_password));
+ request.addHTTPHeaderField(
+ WebString::fromUTF8("X-Google-Relay-Auth"),
+ WebString::fromUTF8(allocator_->config_.relay_password));
+ request.addHTTPHeaderField(WebString::fromUTF8("X-Session-Type"),
+ WebString::fromUTF8(session_type()));
+ request.addHTTPHeaderField(WebString::fromUTF8("X-Stream-Type"),
+ WebString::fromUTF8(name()));
+
+ relay_session_request_->loadAsynchronously(request, this);
+}
+
+void P2PPortAllocatorSession::ParseRelayResponse() {
+ std::vector<std::pair<std::string, std::string> > value_pairs;
+ if (!base::SplitStringIntoKeyValuePairs(relay_session_response_, '=', '\n',
+ &value_pairs)) {
+ LOG(ERROR) << "Received invalid response from relay server";
+ return;
+ }
+
+ relay_username_.clear();
+ relay_password_.clear();
+ relay_ip_.Clear();
+ relay_udp_port_ = 0;
+ relay_tcp_port_ = 0;
+ relay_ssltcp_port_ = 0;
+
+ for (std::vector<std::pair<std::string, std::string> >::iterator
+ it = value_pairs.begin();
+ it != value_pairs.end(); ++it) {
+ std::string key;
+ std::string value;
+ TrimWhitespaceASCII(it->first, TRIM_ALL, &key);
+ TrimWhitespaceASCII(it->second, TRIM_ALL, &value);
+
+ if (key == "username") {
+ relay_username_ = value;
+ } else if (key == "password") {
+ relay_password_ = value;
+ } else if (key == "relay.ip") {
+ relay_ip_.SetIP(value);
+ if (relay_ip_.ip() == 0) {
+ LOG(ERROR) << "Received unresolved relay server address: " << value;
+ return;
+ }
+ } else if (key == "relay.udp_port") {
+ if (!ParsePortNumber(value, &relay_udp_port_))
+ return;
+ } else if (key == "relay.tcp_port") {
+ if (!ParsePortNumber(value, &relay_tcp_port_))
+ return;
+ } else if (key == "relay.ssltcp_port") {
+ if (!ParsePortNumber(value, &relay_ssltcp_port_))
+ return;
+ }
+ }
+
+ AddConfig();
+}
+
+void P2PPortAllocatorSession::AddConfig() {
+ cricket::PortConfiguration* config =
+ new cricket::PortConfiguration(stun_server_address_,
+ relay_username_, relay_password_, "");
+
+ cricket::PortConfiguration::PortList ports;
+ if (relay_ip_.ip() != 0) {
+ if (relay_udp_port_ > 0) {
+ talk_base::SocketAddress address(relay_ip_.ip(), relay_udp_port_);
+ ports.push_back(cricket::ProtocolAddress(address, cricket::PROTO_UDP));
+ }
+ if (relay_tcp_port_ > 0) {
+ talk_base::SocketAddress address(relay_ip_.ip(), relay_tcp_port_);
+ ports.push_back(cricket::ProtocolAddress(address, cricket::PROTO_TCP));
+ }
+ if (relay_ssltcp_port_ > 0) {
+ talk_base::SocketAddress address(relay_ip_.ip(), relay_ssltcp_port_);
+ ports.push_back(cricket::ProtocolAddress(address, cricket::PROTO_SSLTCP));
+ }
+ }
+ config->AddRelay(ports, 0.0f);
+ ConfigReady(config);
}
} // namespace content
diff --git a/content/renderer/p2p/port_allocator.h b/content/renderer/p2p/port_allocator.h
index 0761ba2..fe5511a 100644
--- a/content/renderer/p2p/port_allocator.h
+++ b/content/renderer/p2p/port_allocator.h
@@ -8,17 +8,26 @@
#include "base/memory/ref_counted.h"
#include "net/base/net_util.h"
#include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
#include "webkit/glue/p2p_transport.h"
+namespace WebKit {
+class WebFrame;
+class WebURLLoader;
+} // namespace WebKit
+
namespace content {
class P2PHostAddressRequest;
class P2PPortAllocatorSession;
class P2PSocketDispatcher;
-class P2PPortAllocator : public cricket::BasicPortAllocator{
+// TODO(sergeyu): There is overlap between this class and
+// HttpPortAllocator. Refactor HttpPortAllocator
+class P2PPortAllocator : public cricket::BasicPortAllocator {
public:
- P2PPortAllocator(P2PSocketDispatcher* socket_dispatcher,
+ P2PPortAllocator(WebKit::WebFrame* web_frame,
+ P2PSocketDispatcher* socket_dispatcher,
talk_base::NetworkManager* network_manager,
talk_base::PacketSocketFactory* socket_factory,
const webkit_glue::P2PTransport::Config& config);
@@ -31,13 +40,15 @@ class P2PPortAllocator : public cricket::BasicPortAllocator{
private:
friend class P2PPortAllocatorSession;
+ WebKit::WebFrame* web_frame_;
P2PSocketDispatcher* socket_dispatcher_;
webkit_glue::P2PTransport::Config config_;
DISALLOW_COPY_AND_ASSIGN(P2PPortAllocator);
};
-class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession {
+class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession,
+ public WebKit::WebURLLoaderClient {
public:
P2PPortAllocatorSession(
P2PPortAllocator* allocator,
@@ -45,6 +56,16 @@ class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession {
const std::string& session_type);
virtual ~P2PPortAllocatorSession();
+ // WebKit::WebURLLoaderClient overrides.
+ virtual void didReceiveData(WebKit::WebURLLoader* loader,
+ const char* data,
+ int data_length,
+ int encoded_data_length) OVERRIDE;
+ virtual void didFinishLoading(WebKit::WebURLLoader* loader,
+ double finish_time) OVERRIDE;
+ virtual void didFail(WebKit::WebURLLoader* loader,
+ const WebKit::WebURLError& error) OVERRIDE;
+
protected:
// Overrides for cricket::BasicPortAllocatorSession.
virtual void GetPortConfigurations() OVERRIDE;
@@ -53,9 +74,25 @@ class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession {
void ResolveStunServerAddress();
void OnStunServerAddress(const net::IPAddressNumber& address);
+ void AllocateRelaySession();
+ void ParseRelayResponse();
+
+ void AddConfig();
+
P2PPortAllocator* allocator_;
scoped_refptr<P2PHostAddressRequest> stun_address_request_;
+ talk_base::SocketAddress stun_server_address_;
+
+ scoped_ptr<WebKit::WebURLLoader> relay_session_request_;
+ int relay_session_attemtps_;
+ std::string relay_session_response_;
+ std::string relay_username_;
+ std::string relay_password_;
+ talk_base::SocketAddress relay_ip_;
+ int relay_udp_port_;
+ int relay_tcp_port_;
+ int relay_ssltcp_port_;
DISALLOW_COPY_AND_ASSIGN(P2PPortAllocatorSession);
};