Proxy detection is important feature for the P2P sockets, as

it provides additional security for enterprise use cases.

Communication between webrtc endpoints happens through UDP/TCP/STUN
with or without the help of TURN server.

In case of firewall restrictions like outgoing UDP block and allowing
only secure ports, direct communication between two endbecomes impossible 
without the help of TURN.
In the presence of proxies, direct communication even to TURN server also 
becomes impossible without first esablishing connection with the proxy.

This CL is trying to address the last problem. 
If proxies are configured(HTTP/S/SOCKS) send data(stun+media) through it.

jingle_glue::ProxyResolvingClientSocket solves the problem of proxy detection and establishing the connection and also it's a type of net::StreamSocket, this class can be directly used in P2PSocketHostTcpBase.

R=sergeyu@chromium.org,juberti@chromium.org,thakis@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207919 0039d316-1c4b-4281-b951-d872f2087c98
parent f6dfbfd6
......@@ -15,6 +15,7 @@
#include "net/base/net_log.h"
#include "net/base/sys_addrinfo.h"
#include "net/dns/single_request_host_resolver.h"
#include "net/url_request/url_request_context_getter.h"
using content::BrowserMessageFilter;
using content::BrowserThread;
......@@ -83,8 +84,10 @@ class P2PSocketDispatcherHost::DnsRequest {
};
P2PSocketDispatcherHost::P2PSocketDispatcherHost(
content::ResourceContext* resource_context)
content::ResourceContext* resource_context,
net::URLRequestContextGetter* url_context)
: resource_context_(resource_context),
url_context_(url_context),
monitoring_networks_(false) {
}
......@@ -188,7 +191,7 @@ void P2PSocketDispatcherHost::OnCreateSocket(
}
scoped_ptr<P2PSocketHost> socket(
P2PSocketHost::Create(this, socket_id, type));
P2PSocketHost::Create(this, socket_id, type, url_context_));
if (!socket) {
Send(new P2PMsg_OnError(socket_id));
......
......@@ -13,6 +13,10 @@
#include "net/base/ip_endpoint.h"
#include "net/base/network_change_notifier.h"
namespace net {
class URLRequestContextGetter;
}
namespace content {
class P2PSocketHost;
......@@ -22,7 +26,8 @@ class P2PSocketDispatcherHost
: public content::BrowserMessageFilter,
public net::NetworkChangeNotifier::IPAddressObserver {
public:
P2PSocketDispatcherHost(content::ResourceContext* resource_context);
P2PSocketDispatcherHost(content::ResourceContext* resource_context,
net::URLRequestContextGetter* url_context);
// content::BrowserMessageFilter overrides.
virtual void OnChannelClosing() OVERRIDE;
......@@ -72,6 +77,7 @@ class P2PSocketDispatcherHost
const net::IPAddressNumber& result);
content::ResourceContext* resource_context_;
scoped_refptr<net::URLRequestContextGetter> url_context_;
SocketsMap sockets_;
......
......@@ -72,7 +72,8 @@ bool P2PSocketHost::IsRequestOrResponse(StunMessageType type) {
// static
P2PSocketHost* P2PSocketHost::Create(
IPC::Sender* message_sender, int id, P2PSocketType type) {
IPC::Sender* message_sender, int id, P2PSocketType type,
net::URLRequestContextGetter* url_context) {
switch (type) {
case P2P_SOCKET_UDP:
return new P2PSocketHostUdp(message_sender, id);
......@@ -86,16 +87,12 @@ P2PSocketHost* P2PSocketHost::Create(
message_sender, id, P2P_SOCKET_STUN_TCP_CLIENT);
case P2P_SOCKET_TCP_CLIENT:
return new P2PSocketHostTcp(message_sender, id, type);
case P2P_SOCKET_STUN_TCP_CLIENT:
return new P2PSocketHostStunTcp(message_sender, id, type);
case P2P_SOCKET_SSLTCP_CLIENT:
return new P2PSocketHostTcp(message_sender, id, type);
return new P2PSocketHostTcp(message_sender, id, type, url_context);
case P2P_SOCKET_STUN_TCP_CLIENT:
case P2P_SOCKET_STUN_SSLTCP_CLIENT:
return new P2PSocketHostStunTcp(message_sender, id, type);
return new P2PSocketHostStunTcp(message_sender, id, type, url_context);
}
NOTREACHED();
......
......@@ -14,6 +14,10 @@ namespace IPC {
class Sender;
}
namespace net {
class URLRequestContextGetter;
}
namespace content {
// Base class for P2P sockets.
......@@ -22,7 +26,8 @@ class CONTENT_EXPORT P2PSocketHost {
static const int kStunHeaderSize = 20;
// Creates P2PSocketHost of the specific type.
static P2PSocketHost* Create(IPC::Sender* message_sender,
int id, P2PSocketType type);
int id, P2PSocketType type,
net::URLRequestContextGetter* url_context);
virtual ~P2PSocketHost();
......@@ -38,8 +43,7 @@ class CONTENT_EXPORT P2PSocketHost {
const net::IPEndPoint& remote_address, int id) = 0;
protected:
friend class P2PSocketHostTcpTest;
friend class P2PSocketHostStunTcpTest;
friend class P2PSocketHostTcpTestBase;
enum StunMessageType {
STUN_BINDING_REQUEST = 0x0001,
......
......@@ -8,10 +8,12 @@
#include "content/common/p2p_messages.h"
#include "ipc/ipc_sender.h"
#include "jingle/glue/fake_ssl_client_socket.h"
#include "jingle/glue/proxy_resolving_client_socket.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/socket/tcp_client_socket.h"
#include "net/url_request/url_request_context_getter.h"
namespace {
......@@ -30,13 +32,14 @@ bool IsSslClientSocket(content::P2PSocketType type) {
namespace content {
P2PSocketHostTcpBase::P2PSocketHostTcpBase(IPC::Sender* message_sender,
int id,
P2PSocketType type)
P2PSocketHostTcpBase::P2PSocketHostTcpBase(
IPC::Sender* message_sender, int id,
P2PSocketType type, net::URLRequestContextGetter* url_context)
: P2PSocketHost(message_sender, id),
write_pending_(false),
connected_(false),
type_(type) {
type_(type),
url_context_(url_context) {
}
P2PSocketHostTcpBase::~P2PSocketHostTcpBase() {
......@@ -60,28 +63,43 @@ bool P2PSocketHostTcpBase::InitAccepted(const net::IPEndPoint& remote_address,
}
bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
const net::IPEndPoint& remote_address) {
const net::IPEndPoint& remote_address) {
DCHECK_EQ(state_, STATE_UNINITIALIZED);
remote_address_ = remote_address;
state_ = STATE_CONNECTING;
scoped_ptr<net::TCPClientSocket> tcp_socket(new net::TCPClientSocket(
net::AddressList(remote_address),
NULL, net::NetLog::Source()));
if (tcp_socket->Bind(local_address) != net::OK) {
OnError();
return false;
}
net::HostPortPair dest_host_port_pair =
net::HostPortPair::FromIPEndPoint(remote_address);
// TODO(mallinath) - We are ignoring local_address altogether. We should
// find a way to inject this into ProxyResolvingClientSocket. This could be
// a problem on multi-homed host.
// The default SSLConfig is good enough for us for now.
const net::SSLConfig ssl_config;
socket_.reset(new jingle_glue::ProxyResolvingClientSocket(
NULL, // Default socket pool provided by the net::Proxy.
url_context_,
ssl_config,
dest_host_port_pair));
if (IsSslClientSocket(type_)) {
socket_.reset(new jingle_glue::FakeSSLClientSocket(tcp_socket.release()));
} else {
socket_ = tcp_socket.PassAs<net::StreamSocket>();
socket_.reset(new jingle_glue::FakeSSLClientSocket(socket_.release()));
}
int result = socket_->Connect(
base::Bind(&P2PSocketHostTcp::OnConnected, base::Unretained(this)));
if (result != net::ERR_IO_PENDING) {
OnConnected(result);
int status = socket_->Connect(
base::Bind(&P2PSocketHostTcpBase::OnConnected,
base::Unretained(this)));
if (status != net::ERR_IO_PENDING) {
// We defer execution of ProcessConnectDone instead of calling it
// directly here as the caller may not expect an error/close to
// happen here. This is okay, as from the caller's point of view,
// the connect always happens asynchronously.
base::MessageLoop* message_loop = base::MessageLoop::current();
CHECK(message_loop);
message_loop->PostTask(
FROM_HERE,
base::Bind(&P2PSocketHostTcpBase::OnConnected,
base::Unretained(this), status));
}
return state_ != STATE_ERROR;
......@@ -285,10 +303,10 @@ void P2PSocketHostTcpBase::DidCompleteRead(int result) {
}
}
P2PSocketHostTcp::P2PSocketHostTcp(IPC::Sender* message_sender,
int id,
P2PSocketType type)
: P2PSocketHostTcpBase(message_sender, id, type) {
P2PSocketHostTcp::P2PSocketHostTcp(
IPC::Sender* message_sender, int id,
P2PSocketType type, net::URLRequestContextGetter* url_context)
: P2PSocketHostTcpBase(message_sender, id, type, url_context) {
DCHECK(type == P2P_SOCKET_TCP_CLIENT || type == P2P_SOCKET_SSLTCP_CLIENT);
}
......@@ -322,10 +340,10 @@ void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to,
}
// P2PSocketHostStunTcp
P2PSocketHostStunTcp::P2PSocketHostStunTcp(IPC::Sender* message_sender,
int id,
P2PSocketType type)
: P2PSocketHostTcpBase(message_sender, id, type) {
P2PSocketHostStunTcp::P2PSocketHostStunTcp(
IPC::Sender* message_sender, int id,
P2PSocketType type, net::URLRequestContextGetter* url_context)
: P2PSocketHostTcpBase(message_sender, id, type, url_context) {
DCHECK(type == P2P_SOCKET_STUN_TCP_CLIENT ||
type == P2P_SOCKET_STUN_SSLTCP_CLIENT);
}
......
......@@ -21,13 +21,17 @@ namespace net {
class DrainableIOBuffer;
class GrowableIOBuffer;
class StreamSocket;
class URLRequestContextGetter;
} // namespace net
namespace content {
class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
public:
P2PSocketHostTcpBase(IPC::Sender* message_sender, int id, P2PSocketType type);
P2PSocketHostTcpBase(IPC::Sender* message_sender,
int id,
P2PSocketType type,
net::URLRequestContextGetter* url_context);
virtual ~P2PSocketHostTcpBase();
bool InitAccepted(const net::IPEndPoint& remote_address,
......@@ -52,9 +56,8 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
void OnError();
private:
friend class P2PSocketHostTcpTest;
friend class P2PSocketHostTcpTestBase;
friend class P2PSocketHostTcpServerTest;
friend class P2PSocketHostStunTcpTest;
void DidCompleteRead(int result);
void DoRead();
......@@ -77,15 +80,18 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
bool write_pending_;
bool connected_;
P2PSocketType type_;
scoped_refptr<net::URLRequestContextGetter> url_context_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketHostTcpBase);
};
class CONTENT_EXPORT P2PSocketHostTcp : public P2PSocketHostTcpBase {
public:
P2PSocketHostTcp(IPC::Sender* message_sender, int id, P2PSocketType type);
P2PSocketHostTcp(IPC::Sender* message_sender,
int id,
P2PSocketType type,
net::URLRequestContextGetter* url_context);
virtual ~P2PSocketHostTcp();
protected:
......@@ -102,7 +108,11 @@ class CONTENT_EXPORT P2PSocketHostTcp : public P2PSocketHostTcpBase {
// Formatting of messages is defined in RFC5766.
class CONTENT_EXPORT P2PSocketHostStunTcp : public P2PSocketHostTcpBase {
public:
P2PSocketHostStunTcp(IPC::Sender* message_sender, int id, P2PSocketType type);
P2PSocketHostStunTcp(IPC::Sender* message_sender,
int id,
P2PSocketType type,
net::URLRequestContextGetter* url_context);
virtual ~P2PSocketHostStunTcp();
protected:
......
......@@ -131,9 +131,10 @@ P2PSocketHost* P2PSocketHostTcpServer::AcceptIncomingTcpConnection(
scoped_ptr<P2PSocketHostTcpBase> result;
if (client_type_ == P2P_SOCKET_TCP_CLIENT) {
result.reset(new P2PSocketHostTcp(message_sender_, id, client_type_));
result.reset(new P2PSocketHostTcp(message_sender_, id, client_type_, NULL));
} else {
result.reset(new P2PSocketHostStunTcp(message_sender_, id, client_type_));
result.reset(new P2PSocketHostStunTcp(
message_sender_, id, client_type_, NULL));
}
if (!result->InitAccepted(remote_address, socket))
return NULL;
......
......@@ -19,15 +19,25 @@ using ::testing::Return;
namespace content {
class P2PSocketHostTcpTest : public testing::Test {
class P2PSocketHostTcpTestBase : public testing::Test {
protected:
explicit P2PSocketHostTcpTestBase(P2PSocketType type)
: socket_type_(type) {
}
virtual void SetUp() OVERRIDE {
EXPECT_CALL(sender_, Send(
MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
socket_host_.reset(new P2PSocketHostTcp(&sender_, 0,
P2P_SOCKET_TCP_CLIENT));
if (socket_type_ == P2P_SOCKET_TCP_CLIENT) {
socket_host_.reset(new P2PSocketHostTcp(
&sender_, 0, P2P_SOCKET_TCP_CLIENT, NULL));
} else {
socket_host_.reset(new P2PSocketHostStunTcp(
&sender_, 0, P2P_SOCKET_STUN_TCP_CLIENT, NULL));
}
socket_ = new FakeSocket(&sent_data_);
socket_->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
socket_host_->socket_.reset(socket_);
......@@ -50,55 +60,28 @@ class P2PSocketHostTcpTest : public testing::Test {
}
std::string sent_data_;
FakeSocket* socket_; // Owned by |socket_host_|.
scoped_ptr<P2PSocketHostTcp> socket_host_;
FakeSocket* socket_; // Owned by |socket_host_|.
scoped_ptr<P2PSocketHostTcpBase> socket_host_;
MockIPCSender sender_;
net::IPEndPoint local_address_;
net::IPEndPoint dest_;
net::IPEndPoint dest2_;
P2PSocketType socket_type_;
};
class P2PSocketHostStunTcpTest : public testing::Test {
class P2PSocketHostTcpTest : public P2PSocketHostTcpTestBase {
protected:
virtual void SetUp() OVERRIDE {
EXPECT_CALL(sender_, Send(
MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
socket_host_.reset(new P2PSocketHostStunTcp(&sender_, 0,
P2P_SOCKET_STUN_TCP_CLIENT));
socket_ = new FakeSocket(&sent_data_);
socket_->SetLocalAddress(ParseAddress(kTestLocalIpAddress, kTestPort1));
socket_host_->socket_.reset(socket_);
dest_ = ParseAddress(kTestIpAddress1, kTestPort1);
local_address_ = ParseAddress(kTestLocalIpAddress, kTestPort1);
socket_host_->remote_address_ = dest_;
socket_host_->state_ = P2PSocketHost::STATE_CONNECTING;
socket_host_->OnConnected(net::OK);
}
P2PSocketHostTcpTest() : P2PSocketHostTcpTestBase(P2P_SOCKET_TCP_CLIENT) { }
};
std::string IntToSize(int size) {
std::string result;
uint16 size16 = base::HostToNet16(size);
result.resize(sizeof(size16));
memcpy(&result[0], &size16, sizeof(size16));
return result;
class P2PSocketHostStunTcpTest : public P2PSocketHostTcpTestBase {
protected:
P2PSocketHostStunTcpTest()
: P2PSocketHostTcpTestBase(P2P_SOCKET_STUN_TCP_CLIENT) {
}
std::string sent_data_;
FakeSocket* socket_; // Owned by |socket_host_|.
scoped_ptr<P2PSocketHostStunTcp> socket_host_;
MockIPCSender sender_;
net::IPEndPoint local_address_;
net::IPEndPoint dest_;
net::IPEndPoint dest2_;
};
// Verify that we can send STUN message and that they are formatted
......
......@@ -684,7 +684,9 @@ void RenderProcessHostImpl::CreateMessageFilters() {
base::Unretained(widget_helper_.get()))));
#if defined(ENABLE_WEBRTC)
channel_->AddFilter(new P2PSocketDispatcherHost(resource_context));
channel_->AddFilter(new P2PSocketDispatcherHost(
resource_context,
browser_context->GetRequestContextForRenderProcess(GetID())));
#endif
channel_->AddFilter(new TraceMessageFilter());
......
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