| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/p2p/ipc_socket_factory.h" | 5 #include "content/renderer/p2p/ipc_socket_factory.h" |
| 6 | 6 |
| 7 #include <deque> | 7 #include <deque> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/message_loop/message_loop_proxy.h" | 12 #include "base/message_loop/message_loop_proxy.h" |
| 13 #include "content/public/renderer/p2p_socket_client_delegate.h" |
| 13 #include "content/renderer/p2p/host_address_request.h" | 14 #include "content/renderer/p2p/host_address_request.h" |
| 14 #include "content/renderer/p2p/socket_client.h" | 15 #include "content/renderer/p2p/socket_client_impl.h" |
| 15 #include "content/renderer/p2p/socket_dispatcher.h" | 16 #include "content/renderer/p2p/socket_dispatcher.h" |
| 16 #include "jingle/glue/utils.h" | 17 #include "jingle/glue/utils.h" |
| 17 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" | 18 #include "third_party/libjingle/source/talk/base/asyncpacketsocket.h" |
| 18 | 19 |
| 19 namespace content { | 20 namespace content { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 bool IsTcpClientSocket(P2PSocketType type) { | 24 bool IsTcpClientSocket(P2PSocketType type) { |
| 24 return (type == P2P_SOCKET_STUN_TCP_CLIENT) || | 25 return (type == P2P_SOCKET_STUN_TCP_CLIENT) || |
| 25 (type == P2P_SOCKET_TCP_CLIENT) || | 26 (type == P2P_SOCKET_TCP_CLIENT) || |
| 26 (type == P2P_SOCKET_STUN_SSLTCP_CLIENT) || | 27 (type == P2P_SOCKET_STUN_SSLTCP_CLIENT) || |
| 27 (type == P2P_SOCKET_SSLTCP_CLIENT) || | 28 (type == P2P_SOCKET_SSLTCP_CLIENT) || |
| 28 (type == P2P_SOCKET_TLS_CLIENT) || | 29 (type == P2P_SOCKET_TLS_CLIENT) || |
| 29 (type == P2P_SOCKET_STUN_TLS_CLIENT); | 30 (type == P2P_SOCKET_STUN_TLS_CLIENT); |
| 30 } | 31 } |
| 31 | 32 |
| 32 // TODO(miu): This needs tuning. http://crbug.com/237960 | 33 // TODO(miu): This needs tuning. http://crbug.com/237960 |
| 33 const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB | 34 const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB |
| 34 | 35 |
| 35 // IpcPacketSocket implements talk_base::AsyncPacketSocket interface | 36 // IpcPacketSocket implements talk_base::AsyncPacketSocket interface |
| 36 // using P2PSocketClient that works over IPC-channel. It must be used | 37 // using P2PSocketClient that works over IPC-channel. It must be used |
| 37 // on the thread it was created. | 38 // on the thread it was created. |
| 38 class IpcPacketSocket : public talk_base::AsyncPacketSocket, | 39 class IpcPacketSocket : public talk_base::AsyncPacketSocket, |
| 39 public P2PSocketClient::Delegate { | 40 public P2PSocketClientDelegate { |
| 40 public: | 41 public: |
| 41 IpcPacketSocket(); | 42 IpcPacketSocket(); |
| 42 virtual ~IpcPacketSocket(); | 43 virtual ~IpcPacketSocket(); |
| 43 | 44 |
| 44 // Always takes ownership of client even if initialization fails. | 45 // Always takes ownership of client even if initialization fails. |
| 45 bool Init(P2PSocketType type, P2PSocketClient* client, | 46 bool Init(P2PSocketType type, P2PSocketClientImpl* client, |
| 46 const talk_base::SocketAddress& local_address, | 47 const talk_base::SocketAddress& local_address, |
| 47 const talk_base::SocketAddress& remote_address); | 48 const talk_base::SocketAddress& remote_address); |
| 48 | 49 |
| 49 // talk_base::AsyncPacketSocket interface. | 50 // talk_base::AsyncPacketSocket interface. |
| 50 virtual talk_base::SocketAddress GetLocalAddress() const OVERRIDE; | 51 virtual talk_base::SocketAddress GetLocalAddress() const OVERRIDE; |
| 51 virtual talk_base::SocketAddress GetRemoteAddress() const OVERRIDE; | 52 virtual talk_base::SocketAddress GetRemoteAddress() const OVERRIDE; |
| 52 virtual int Send(const void *pv, size_t cb, | 53 virtual int Send(const void *pv, size_t cb, |
| 53 talk_base::DiffServCodePoint dscp) OVERRIDE; | 54 talk_base::DiffServCodePoint dscp) OVERRIDE; |
| 54 virtual int SendTo(const void *pv, size_t cb, | 55 virtual int SendTo(const void *pv, size_t cb, |
| 55 const talk_base::SocketAddress& addr, | 56 const talk_base::SocketAddress& addr, |
| 56 talk_base::DiffServCodePoint dscp) OVERRIDE; | 57 talk_base::DiffServCodePoint dscp) OVERRIDE; |
| 57 virtual int Close() OVERRIDE; | 58 virtual int Close() OVERRIDE; |
| 58 virtual State GetState() const OVERRIDE; | 59 virtual State GetState() const OVERRIDE; |
| 59 virtual int GetOption(talk_base::Socket::Option opt, int* value) OVERRIDE; | 60 virtual int GetOption(talk_base::Socket::Option opt, int* value) OVERRIDE; |
| 60 virtual int SetOption(talk_base::Socket::Option opt, int value) OVERRIDE; | 61 virtual int SetOption(talk_base::Socket::Option opt, int value) OVERRIDE; |
| 61 virtual int GetError() const OVERRIDE; | 62 virtual int GetError() const OVERRIDE; |
| 62 virtual void SetError(int error) OVERRIDE; | 63 virtual void SetError(int error) OVERRIDE; |
| 63 | 64 |
| 64 // P2PSocketClient::Delegate implementation. | 65 // P2PSocketClientDelegate implementation. |
| 65 virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE; | 66 virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE; |
| 66 virtual void OnIncomingTcpConnection(const net::IPEndPoint& address, | 67 virtual void OnIncomingTcpConnection( |
| 67 P2PSocketClient* client) OVERRIDE; | 68 const net::IPEndPoint& address, |
| 69 P2PSocketClient* client) OVERRIDE; |
| 68 virtual void OnSendComplete() OVERRIDE; | 70 virtual void OnSendComplete() OVERRIDE; |
| 69 virtual void OnError() OVERRIDE; | 71 virtual void OnError() OVERRIDE; |
| 70 virtual void OnDataReceived(const net::IPEndPoint& address, | 72 virtual void OnDataReceived(const net::IPEndPoint& address, |
| 71 const std::vector<char>& data) OVERRIDE; | 73 const std::vector<char>& data) OVERRIDE; |
| 72 | 74 |
| 73 private: | 75 private: |
| 74 enum InternalState { | 76 enum InternalState { |
| 75 IS_UNINITIALIZED, | 77 IS_UNINITIALIZED, |
| 76 IS_OPENING, | 78 IS_OPENING, |
| 77 IS_OPEN, | 79 IS_OPEN, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 } | 144 } |
| 143 } | 145 } |
| 144 | 146 |
| 145 void IpcPacketSocket::TraceSendThrottlingState() const { | 147 void IpcPacketSocket::TraceSendThrottlingState() const { |
| 146 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(), | 148 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(), |
| 147 send_bytes_available_); | 149 send_bytes_available_); |
| 148 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(), | 150 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(), |
| 149 in_flight_packet_sizes_.size()); | 151 in_flight_packet_sizes_.size()); |
| 150 } | 152 } |
| 151 | 153 |
| 152 bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client, | 154 bool IpcPacketSocket::Init(P2PSocketType type, |
| 155 P2PSocketClientImpl* client, |
| 153 const talk_base::SocketAddress& local_address, | 156 const talk_base::SocketAddress& local_address, |
| 154 const talk_base::SocketAddress& remote_address) { | 157 const talk_base::SocketAddress& remote_address) { |
| 155 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | 158 DCHECK_EQ(base::MessageLoop::current(), message_loop_); |
| 156 DCHECK_EQ(state_, IS_UNINITIALIZED); | 159 DCHECK_EQ(state_, IS_UNINITIALIZED); |
| 157 | 160 |
| 158 type_ = type; | 161 type_ = type; |
| 159 client_ = client; | 162 client_ = client; |
| 160 local_address_ = local_address; | 163 local_address_ = local_address; |
| 161 remote_address_ = remote_address; | 164 remote_address_ = remote_address; |
| 162 state_ = IS_OPENING; | 165 state_ = IS_OPENING; |
| 163 | 166 |
| 164 net::IPEndPoint local_endpoint; | 167 net::IPEndPoint local_endpoint; |
| 165 if (!jingle_glue::SocketAddressToIPEndPoint( | 168 if (!jingle_glue::SocketAddressToIPEndPoint( |
| 166 local_address, &local_endpoint)) { | 169 local_address, &local_endpoint)) { |
| 167 return false; | 170 return false; |
| 168 } | 171 } |
| 169 | 172 |
| 170 net::IPEndPoint remote_endpoint; | 173 net::IPEndPoint remote_endpoint; |
| 171 if (!remote_address.IsNil() && | 174 if (!remote_address.IsNil() && |
| 172 !jingle_glue::SocketAddressToIPEndPoint( | 175 !jingle_glue::SocketAddressToIPEndPoint( |
| 173 remote_address, &remote_endpoint)) { | 176 remote_address, &remote_endpoint)) { |
| 174 return false; | 177 return false; |
| 175 } | 178 } |
| 176 | 179 |
| 177 client_->Init(type, local_endpoint, remote_endpoint, this); | 180 client->Init(type, local_endpoint, remote_endpoint, this); |
| 178 | 181 |
| 179 return true; | 182 return true; |
| 180 } | 183 } |
| 181 | 184 |
| 182 void IpcPacketSocket::InitAcceptedTcp( | 185 void IpcPacketSocket::InitAcceptedTcp( |
| 183 P2PSocketClient* client, | 186 P2PSocketClient* client, |
| 184 const talk_base::SocketAddress& local_address, | 187 const talk_base::SocketAddress& local_address, |
| 185 const talk_base::SocketAddress& remote_address) { | 188 const talk_base::SocketAddress& remote_address) { |
| 186 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | 189 DCHECK_EQ(base::MessageLoop::current(), message_loop_); |
| 187 DCHECK_EQ(state_, IS_UNINITIALIZED); | 190 DCHECK_EQ(state_, IS_UNINITIALIZED); |
| 188 | 191 |
| 189 client_ = client; | 192 client_ = client; |
| 190 local_address_ = local_address; | 193 local_address_ = local_address; |
| 191 remote_address_ = remote_address; | 194 remote_address_ = remote_address; |
| 192 state_ = IS_OPEN; | 195 state_ = IS_OPEN; |
| 193 TraceSendThrottlingState(); | 196 TraceSendThrottlingState(); |
| 194 client_->set_delegate(this); | 197 client_->SetDelegate(this); |
| 195 } | 198 } |
| 196 | 199 |
| 197 // talk_base::AsyncPacketSocket interface. | 200 // talk_base::AsyncPacketSocket interface. |
| 198 talk_base::SocketAddress IpcPacketSocket::GetLocalAddress() const { | 201 talk_base::SocketAddress IpcPacketSocket::GetLocalAddress() const { |
| 199 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | 202 DCHECK_EQ(base::MessageLoop::current(), message_loop_); |
| 200 return local_address_; | 203 return local_address_; |
| 201 } | 204 } |
| 202 | 205 |
| 203 talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const { | 206 talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const { |
| 204 DCHECK_EQ(base::MessageLoop::current(), message_loop_); | 207 DCHECK_EQ(base::MessageLoop::current(), message_loop_); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 231 break; | 234 break; |
| 232 } | 235 } |
| 233 | 236 |
| 234 if (data_size == 0) { | 237 if (data_size == 0) { |
| 235 NOTREACHED(); | 238 NOTREACHED(); |
| 236 return 0; | 239 return 0; |
| 237 } | 240 } |
| 238 | 241 |
| 239 if (data_size > send_bytes_available_) { | 242 if (data_size > send_bytes_available_) { |
| 240 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock", | 243 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock", |
| 241 TRACE_EVENT_SCOPE_THREAD, "id", client_->socket_id()); | 244 TRACE_EVENT_SCOPE_THREAD, |
| 245 "id", |
| 246 client_->GetSocketID()); |
| 242 writable_signal_expected_ = true; | 247 writable_signal_expected_ = true; |
| 243 error_ = EWOULDBLOCK; | 248 error_ = EWOULDBLOCK; |
| 244 return -1; | 249 return -1; |
| 245 } | 250 } |
| 246 | 251 |
| 247 net::IPEndPoint address_chrome; | 252 net::IPEndPoint address_chrome; |
| 248 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { | 253 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { |
| 249 NOTREACHED(); | 254 NOTREACHED(); |
| 250 error_ = EINVAL; | 255 error_ = EINVAL; |
| 251 return -1; | 256 return -1; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 P2PSocketDispatcher* socket_dispatcher) | 401 P2PSocketDispatcher* socket_dispatcher) |
| 397 : socket_dispatcher_(socket_dispatcher) { | 402 : socket_dispatcher_(socket_dispatcher) { |
| 398 } | 403 } |
| 399 | 404 |
| 400 IpcPacketSocketFactory::~IpcPacketSocketFactory() { | 405 IpcPacketSocketFactory::~IpcPacketSocketFactory() { |
| 401 } | 406 } |
| 402 | 407 |
| 403 talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket( | 408 talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket( |
| 404 const talk_base::SocketAddress& local_address, int min_port, int max_port) { | 409 const talk_base::SocketAddress& local_address, int min_port, int max_port) { |
| 405 talk_base::SocketAddress crome_address; | 410 talk_base::SocketAddress crome_address; |
| 406 P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); | 411 P2PSocketClientImpl* socket_client = |
| 412 new P2PSocketClientImpl(socket_dispatcher_); |
| 407 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); | 413 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); |
| 408 // TODO(sergeyu): Respect local_address and port limits here (need | 414 // TODO(sergeyu): Respect local_address and port limits here (need |
| 409 // to pass them over IPC channel to the browser). | 415 // to pass them over IPC channel to the browser). |
| 410 if (!socket->Init(P2P_SOCKET_UDP, socket_client, | 416 if (!socket->Init(P2P_SOCKET_UDP, socket_client, |
| 411 local_address, talk_base::SocketAddress())) { | 417 local_address, talk_base::SocketAddress())) { |
| 412 return NULL; | 418 return NULL; |
| 413 } | 419 } |
| 414 return socket.release(); | 420 return socket.release(); |
| 415 } | 421 } |
| 416 | 422 |
| 417 talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket( | 423 talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket( |
| 418 const talk_base::SocketAddress& local_address, int min_port, int max_port, | 424 const talk_base::SocketAddress& local_address, int min_port, int max_port, |
| 419 int opts) { | 425 int opts) { |
| 420 // TODO(sergeyu): Implement SSL support. | 426 // TODO(sergeyu): Implement SSL support. |
| 421 if (opts & talk_base::PacketSocketFactory::OPT_SSLTCP) | 427 if (opts & talk_base::PacketSocketFactory::OPT_SSLTCP) |
| 422 return NULL; | 428 return NULL; |
| 423 | 429 |
| 424 P2PSocketType type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? | 430 P2PSocketType type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? |
| 425 P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER; | 431 P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER; |
| 426 P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); | 432 P2PSocketClientImpl* socket_client = |
| 433 new P2PSocketClientImpl(socket_dispatcher_); |
| 427 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); | 434 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); |
| 428 if (!socket->Init(type, socket_client, local_address, | 435 if (!socket->Init(type, socket_client, local_address, |
| 429 talk_base::SocketAddress())) { | 436 talk_base::SocketAddress())) { |
| 430 return NULL; | 437 return NULL; |
| 431 } | 438 } |
| 432 return socket.release(); | 439 return socket.release(); |
| 433 } | 440 } |
| 434 | 441 |
| 435 talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket( | 442 talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket( |
| 436 const talk_base::SocketAddress& local_address, | 443 const talk_base::SocketAddress& local_address, |
| 437 const talk_base::SocketAddress& remote_address, | 444 const talk_base::SocketAddress& remote_address, |
| 438 const talk_base::ProxyInfo& proxy_info, | 445 const talk_base::ProxyInfo& proxy_info, |
| 439 const std::string& user_agent, int opts) { | 446 const std::string& user_agent, int opts) { |
| 440 P2PSocketType type; | 447 P2PSocketType type; |
| 441 if (opts & talk_base::PacketSocketFactory::OPT_SSLTCP) { | 448 if (opts & talk_base::PacketSocketFactory::OPT_SSLTCP) { |
| 442 type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? | 449 type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? |
| 443 P2P_SOCKET_STUN_SSLTCP_CLIENT : P2P_SOCKET_SSLTCP_CLIENT; | 450 P2P_SOCKET_STUN_SSLTCP_CLIENT : P2P_SOCKET_SSLTCP_CLIENT; |
| 444 } else if (opts & talk_base::PacketSocketFactory::OPT_TLS) { | 451 } else if (opts & talk_base::PacketSocketFactory::OPT_TLS) { |
| 445 type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? | 452 type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? |
| 446 P2P_SOCKET_STUN_TLS_CLIENT : P2P_SOCKET_TLS_CLIENT; | 453 P2P_SOCKET_STUN_TLS_CLIENT : P2P_SOCKET_TLS_CLIENT; |
| 447 } else { | 454 } else { |
| 448 type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? | 455 type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ? |
| 449 P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT; | 456 P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT; |
| 450 } | 457 } |
| 451 P2PSocketClient* socket_client = new P2PSocketClient(socket_dispatcher_); | 458 P2PSocketClientImpl* socket_client = |
| 459 new P2PSocketClientImpl(socket_dispatcher_); |
| 452 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); | 460 scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket()); |
| 453 if (!socket->Init(type, socket_client, local_address, | 461 if (!socket->Init(type, socket_client, local_address, remote_address)) |
| 454 remote_address)) | |
| 455 return NULL; | 462 return NULL; |
| 456 return socket.release(); | 463 return socket.release(); |
| 457 } | 464 } |
| 458 | 465 |
| 459 talk_base::AsyncResolverInterface* | 466 talk_base::AsyncResolverInterface* |
| 460 IpcPacketSocketFactory::CreateAsyncResolver() { | 467 IpcPacketSocketFactory::CreateAsyncResolver() { |
| 461 NOTREACHED(); | 468 NOTREACHED(); |
| 462 return NULL; | 469 return NULL; |
| 463 } | 470 } |
| 464 | 471 |
| 465 } // namespace content | 472 } // namespace content |
| OLD | NEW |