Index: chrome/renderer/p2p/ipc_socket_factory.cc |
=================================================================== |
--- chrome/renderer/p2p/ipc_socket_factory.cc (revision 78386) |
+++ chrome/renderer/p2p/ipc_socket_factory.cc (working copy) |
@@ -1,323 +0,0 @@ |
-// Copyright (c) 2011 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 "chrome/renderer/p2p/ipc_socket_factory.h" |
- |
-#include "base/message_loop.h" |
-#include "base/message_loop_proxy.h" |
-#include "chrome/renderer/p2p/socket_client.h" |
-#include "chrome/renderer/p2p/socket_dispatcher.h" |
-#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" |
- |
-namespace { |
- |
-const size_t kIPv4AddressSize = 4; |
- |
-// Chromium and libjingle represent socket addresses differently. The |
-// following two functions are used to convert addresses from one |
-// representation to another. |
-bool ChromeToLibjingleSocketAddress(const net::IPEndPoint& address_chrome, |
- talk_base::SocketAddress* address_lj) { |
- if (address_chrome.GetFamily() != AF_INET) { |
- LOG(ERROR) << "Only IPv4 addresses are supported."; |
- return false; |
- } |
- uint32 ip_as_int = ntohl(*reinterpret_cast<const uint32*>( |
- &address_chrome.address()[0])); |
- *address_lj = talk_base::SocketAddress(ip_as_int, address_chrome.port()); |
- return true; |
-} |
- |
-bool LibjingleToIPEndPoint(const talk_base::SocketAddress& address_lj, |
- net::IPEndPoint* address_chrome) { |
- uint32 ip = htonl(address_lj.ip()); |
- net::IPAddressNumber address; |
- address.resize(kIPv4AddressSize); |
- memcpy(&address[0], &ip, kIPv4AddressSize); |
- *address_chrome = net::IPEndPoint(address, address_lj.port()); |
- return true; |
-} |
- |
-// IpcPacketSocket implements talk_base::AsyncPacketSocket interface |
-// using P2PSocketClient that works over IPC-channel. It must be used |
-// on the thread it was created. |
-class IpcPacketSocket : public talk_base::AsyncPacketSocket, |
- public P2PSocketClient::Delegate { |
- public: |
- IpcPacketSocket(); |
- virtual ~IpcPacketSocket(); |
- |
- bool Init(P2PSocketType type, P2PSocketClient* client, |
- const talk_base::SocketAddress& address); |
- |
- // talk_base::AsyncPacketSocket interface. |
- virtual talk_base::SocketAddress GetLocalAddress(bool* allocated) const; |
- virtual talk_base::SocketAddress GetRemoteAddress() const; |
- virtual int Send(const void *pv, size_t cb); |
- virtual int SendTo(const void *pv, size_t cb, |
- const talk_base::SocketAddress& addr); |
- virtual int Close(); |
- virtual talk_base::Socket::ConnState GetState() const; |
- virtual int GetOption(talk_base::Socket::Option opt, int* value); |
- virtual int SetOption(talk_base::Socket::Option opt, int value); |
- virtual int GetError() const; |
- virtual void SetError(int error); |
- |
- // P2PSocketClient::Delegate |
- virtual void OnOpen(const net::IPEndPoint& address); |
- virtual void OnError(); |
- virtual void OnDataReceived(const net::IPEndPoint& address, |
- const std::vector<char>& data); |
- |
- private: |
- enum State { |
- STATE_UNINITIALIZED, |
- STATE_OPENING, |
- STATE_OPEN, |
- STATE_CLOSED, |
- STATE_ERROR, |
- }; |
- |
- // Message loop on which this socket was created and being used. |
- MessageLoop* message_loop_; |
- |
- // Corresponding P2P socket client. |
- scoped_refptr<P2PSocketClient> client_; |
- |
- // Local address is allocated by the browser process, and the |
- // renderer side doesn't know the address until it receives OnOpen() |
- // event from the browser. |
- talk_base::SocketAddress local_address_; |
- bool address_initialized_; |
- |
- // Remote address for client TCP connections. |
- talk_base::SocketAddress remote_address_; |
- |
- // Current state of the object. |
- State state_; |
- |
- // Current error code. Valid when state_ == STATE_ERROR. |
- int error_; |
- |
- DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket); |
-}; |
- |
-IpcPacketSocket::IpcPacketSocket() |
- : message_loop_(MessageLoop::current()), |
- address_initialized_(false), |
- state_(STATE_UNINITIALIZED), error_(0) { |
-} |
- |
-IpcPacketSocket::~IpcPacketSocket() { |
- if (state_ == STATE_OPENING || state_ == STATE_OPEN || |
- state_ == STATE_ERROR) { |
- Close(); |
- } |
-} |
- |
-bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client, |
- const talk_base::SocketAddress& address) { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- DCHECK_EQ(state_, STATE_UNINITIALIZED); |
- |
- client_ = client; |
- remote_address_ = address; |
- state_ = STATE_OPENING; |
- |
- net::IPEndPoint address_chrome; |
- if (!LibjingleToIPEndPoint(address, &address_chrome)) { |
- return false; |
- } |
- |
- client_->Init(type, address_chrome, this, |
- base::MessageLoopProxy::CreateForCurrentThread()); |
- |
- return true; |
-} |
- |
-// talk_base::AsyncPacketSocket interface. |
-talk_base::SocketAddress IpcPacketSocket::GetLocalAddress( |
- bool* allocated) const { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- |
- *allocated = address_initialized_; |
- return local_address_; |
-} |
- |
-talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- |
- return remote_address_; |
-} |
- |
-int IpcPacketSocket::Send(const void *data, size_t data_size) { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- return SendTo(data, data_size, remote_address_); |
-} |
- |
-int IpcPacketSocket::SendTo(const void *data, size_t data_size, |
- const talk_base::SocketAddress& address) { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- |
- switch (state_) { |
- case STATE_UNINITIALIZED: |
- NOTREACHED(); |
- return EWOULDBLOCK; |
- case STATE_OPENING: |
- return EWOULDBLOCK; |
- case STATE_CLOSED: |
- return ENOTCONN; |
- case STATE_ERROR: |
- return error_; |
- case STATE_OPEN: |
- // Continue sending the packet. |
- break; |
- } |
- |
- const char* data_char = reinterpret_cast<const char*>(data); |
- std::vector<char> data_vector(data_char, data_char + data_size); |
- |
- net::IPEndPoint address_chrome; |
- if (!LibjingleToIPEndPoint(address, &address_chrome)) { |
- // Just drop the packet if we failed to convert the address. |
- return 0; |
- } |
- |
- client_->Send(address_chrome, data_vector); |
- |
- // Fake successful send. The caller ignores result anyway. |
- return data_size; |
-} |
- |
-int IpcPacketSocket::Close() { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- |
- client_->Close(); |
- state_ = STATE_CLOSED; |
- |
- return 0; |
-} |
- |
-talk_base::Socket::ConnState IpcPacketSocket::GetState() const { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- |
- switch (state_) { |
- case STATE_UNINITIALIZED: |
- NOTREACHED(); |
- return talk_base::Socket::CS_CONNECTING; |
- |
- case STATE_OPENING: |
- return talk_base::Socket::CS_CONNECTING; |
- |
- case STATE_OPEN: |
- return talk_base::Socket::CS_CONNECTED; |
- |
- case STATE_CLOSED: |
- case STATE_ERROR: |
- return talk_base::Socket::CS_CLOSED; |
- } |
- |
- NOTREACHED(); |
- return talk_base::Socket::CS_CLOSED; |
-} |
- |
-int IpcPacketSocket::GetOption(talk_base::Socket::Option opt, int* value) { |
- // We don't support socket options for IPC sockets. |
- return -1; |
-} |
- |
-int IpcPacketSocket::SetOption(talk_base::Socket::Option opt, int value) { |
- // We don't support socket options for IPC sockets. |
- // |
- // TODO(sergeyu): Make sure we set proper socket options on the |
- // browser side. |
- return -1; |
-} |
- |
-int IpcPacketSocket::GetError() const { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- return error_; |
-} |
- |
-void IpcPacketSocket::SetError(int error) { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- error_ = error; |
-} |
- |
-void IpcPacketSocket::OnOpen(const net::IPEndPoint& address) { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- |
- if (!ChromeToLibjingleSocketAddress(address, &local_address_)) { |
- // Always expect correct IPv4 address to be allocated. |
- NOTREACHED(); |
- } |
- SignalAddressReady(this, local_address_); |
- address_initialized_ = true; |
- state_ = STATE_OPEN; |
-} |
- |
-void IpcPacketSocket::OnError() { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- state_ = STATE_ERROR; |
- error_ = ECONNABORTED; |
-} |
- |
-void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address, |
- const std::vector<char>& data) { |
- DCHECK_EQ(MessageLoop::current(), message_loop_); |
- |
- talk_base::SocketAddress address_lj; |
- if (!ChromeToLibjingleSocketAddress(address, &address_lj)) { |
- // We should always be able to convert address here because we |
- // don't expect IPv6 address on IPv4 connections. |
- NOTREACHED(); |
- return; |
- } |
- |
- SignalReadPacket(this, &data[0], data.size(), address_lj); |
-} |
- |
-} // namespace |
- |
-IpcPacketSocketFactory::IpcPacketSocketFactory( |
- P2PSocketDispatcher* socket_dispatcher) |
- : socket_dispatcher_(socket_dispatcher) { |
-} |
- |
-IpcPacketSocketFactory::~IpcPacketSocketFactory() { |
-} |
- |
-talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket( |
- const talk_base::SocketAddress& local_address, int min_port, int max_port) { |
- talk_base::SocketAddress crome_address; |
- P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); |
- scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); |
- // TODO(sergeyu): Respect local_address and port limits here (need |
- // to pass them over IPC channel to the browser). |
- if (!socket->Init(P2P_SOCKET_UDP, socket_client, |
- talk_base::SocketAddress())) { |
- return NULL; |
- } |
- |
- // Socket increments reference count if Init() was successful. |
- return socket.release(); |
-} |
- |
-talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket( |
- const talk_base::SocketAddress& local_address, int min_port, int max_port, |
- bool listen, bool ssl) { |
- // TODO(sergeyu): Implement this; |
- NOTIMPLEMENTED(); |
- return NULL; |
-} |
- |
-talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket( |
- const talk_base::SocketAddress& local_address, |
- const talk_base::SocketAddress& remote_address, |
- const talk_base::ProxyInfo& proxy_info, |
- const std::string& user_agent, bool ssl) { |
- // TODO(sergeyu): Implement this; |
- NOTIMPLEMENTED(); |
- return NULL; |
-} |