diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-15 22:16:02 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-15 22:16:02 +0000 |
commit | 6d3ad505c8e8173e98045d845a910f77fab9ffcf (patch) | |
tree | e996bba53b108dabdcb9b0af89eab2e4664a0bf5 /content | |
parent | b0f146ff51b2b37a2e3549c875fb42365ded7a21 (diff) | |
download | chromium_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.cc | 6 | ||||
-rw-r--r-- | content/renderer/p2p/p2p_transport_impl.h | 3 | ||||
-rw-r--r-- | content/renderer/p2p/p2p_transport_impl_unittest.cc | 4 | ||||
-rw-r--r-- | content/renderer/p2p/port_allocator.cc | 198 | ||||
-rw-r--r-- | content/renderer/p2p/port_allocator.h | 43 |
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); }; |