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.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 |