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/browser/renderer_host/p2p/socket_host_tcp.h" | 5 #include "content/browser/renderer_host/p2p/socket_host_tcp.h" |
6 | 6 |
7 #include "base/sys_byteorder.h" | 7 #include "base/sys_byteorder.h" |
8 #include "content/browser/renderer_host/p2p/ssltcp_helper.h" | |
8 #include "content/common/p2p_messages.h" | 9 #include "content/common/p2p_messages.h" |
9 #include "ipc/ipc_sender.h" | 10 #include "ipc/ipc_sender.h" |
10 #include "net/base/io_buffer.h" | 11 #include "net/base/io_buffer.h" |
11 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
12 #include "net/base/net_util.h" | 13 #include "net/base/net_util.h" |
13 #include "net/socket/tcp_client_socket.h" | 14 #include "net/socket/tcp_client_socket.h" |
14 | 15 |
15 namespace { | 16 namespace { |
16 | 17 |
17 typedef uint16 PacketLength; | 18 typedef uint16 PacketLength; |
18 const int kPacketHeaderSize = sizeof(PacketLength); | 19 const int kPacketHeaderSize = sizeof(PacketLength); |
19 const int kReadBufferSize = 4096; | 20 const int kReadBufferSize = 4096; |
20 const int kPacketLengthOffset = 2; | 21 const int kPacketLengthOffset = 2; |
21 const int kTurnChannelDataHeaderSize = 4; | 22 const int kTurnChannelDataHeaderSize = 4; |
22 | |
23 } // namespace | 23 } // namespace |
24 | 24 |
25 namespace content { | 25 namespace content { |
26 | 26 |
27 P2PSocketHostTcpBase::P2PSocketHostTcpBase(IPC::Sender* message_sender, | 27 P2PSocketHostTcpBase::P2PSocketHostTcpBase(IPC::Sender* message_sender, |
28 int id) | 28 int id, bool ssl) |
Sergey Ulanov
2013/06/18 20:01:26
nit: one argument per line please.
| |
29 : P2PSocketHost(message_sender, id), | 29 : P2PSocketHost(message_sender, id), |
30 write_pending_(false), | 30 write_pending_(false), |
31 connected_(false) { | 31 connected_(false) { |
32 if (ssl) { | |
33 ssltcp_helper_.reset(new SsltcpHelper()); | |
34 } | |
32 } | 35 } |
33 | 36 |
34 P2PSocketHostTcpBase::~P2PSocketHostTcpBase() { | 37 P2PSocketHostTcpBase::~P2PSocketHostTcpBase() { |
35 if (state_ == STATE_OPEN) { | 38 if (state_ == STATE_OPEN) { |
36 DCHECK(socket_.get()); | 39 DCHECK(socket_.get()); |
37 socket_.reset(); | 40 socket_.reset(); |
38 } | 41 } |
39 } | 42 } |
40 | 43 |
41 bool P2PSocketHostTcpBase::InitAccepted(const net::IPEndPoint& remote_address, | 44 bool P2PSocketHostTcpBase::InitAccepted(const net::IPEndPoint& remote_address, |
42 net::StreamSocket* socket) { | 45 net::StreamSocket* socket) { |
43 DCHECK(socket); | 46 DCHECK(socket); |
44 DCHECK_EQ(state_, STATE_UNINITIALIZED); | 47 DCHECK_EQ(state_, STATE_UNINITIALIZED); |
45 | 48 |
49 if (ssltcp_helper_.get()) { | |
Sergey Ulanov
2013/06/18 20:01:26
nit: don't need .get() here and in Init().
| |
50 // Init ssltcp helper to server mode. | |
Sergey Ulanov
2013/06/18 20:01:26
You wouldn't need this comment if you used an enum
| |
51 ssltcp_helper_->Init(false); | |
52 } | |
46 remote_address_ = remote_address; | 53 remote_address_ = remote_address; |
47 socket_.reset(socket); | 54 socket_.reset(socket); |
48 state_ = STATE_OPEN; | 55 state_ = STATE_OPEN; |
49 DoRead(); | 56 DoRead(); |
50 return state_ != STATE_ERROR; | 57 return state_ != STATE_ERROR; |
51 } | 58 } |
52 | 59 |
53 bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address, | 60 bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address, |
54 const net::IPEndPoint& remote_address) { | 61 const net::IPEndPoint& remote_address) { |
55 DCHECK_EQ(state_, STATE_UNINITIALIZED); | 62 DCHECK_EQ(state_, STATE_UNINITIALIZED); |
56 | 63 |
64 if (ssltcp_helper_.get()) { | |
65 // Init ssltcp helper to client mode. | |
66 ssltcp_helper_->Init(true); | |
67 } | |
57 remote_address_ = remote_address; | 68 remote_address_ = remote_address; |
58 state_ = STATE_CONNECTING; | 69 state_ = STATE_CONNECTING; |
59 scoped_ptr<net::TCPClientSocket> tcp_socket(new net::TCPClientSocket( | 70 scoped_ptr<net::TCPClientSocket> tcp_socket(new net::TCPClientSocket( |
60 net::AddressList(remote_address), | 71 net::AddressList(remote_address), |
61 NULL, net::NetLog::Source())); | 72 NULL, net::NetLog::Source())); |
62 if (tcp_socket->Bind(local_address) != net::OK) { | 73 if (tcp_socket->Bind(local_address) != net::OK) { |
63 OnError(); | 74 OnError(); |
64 return false; | 75 return false; |
65 } | 76 } |
66 socket_.reset(tcp_socket.release()); | 77 socket_.reset(tcp_socket.release()); |
(...skipping 11 matching lines...) Expand all Loading... | |
78 socket_.reset(); | 89 socket_.reset(); |
79 | 90 |
80 if (state_ == STATE_UNINITIALIZED || state_ == STATE_CONNECTING || | 91 if (state_ == STATE_UNINITIALIZED || state_ == STATE_CONNECTING || |
81 state_ == STATE_OPEN) { | 92 state_ == STATE_OPEN) { |
82 message_sender_->Send(new P2PMsg_OnError(id_)); | 93 message_sender_->Send(new P2PMsg_OnError(id_)); |
83 } | 94 } |
84 | 95 |
85 state_ = STATE_ERROR; | 96 state_ = STATE_ERROR; |
86 } | 97 } |
87 | 98 |
99 int P2PSocketHostTcpBase::MaybeHandleSslHello(char** cur, int* cur_len, | |
100 int* consumed) { | |
101 if (static_cast<size_t>(*cur_len) < | |
102 ssltcp_helper_->remote_hello_message_size()) { | |
103 return 0; | |
104 } | |
105 if (!ssltcp_helper_->IsHelloMessage(*cur)) { | |
106 LOG(ERROR) << "Expect a SSL HELLO message."; | |
107 OnError(); | |
108 return 0; | |
109 } | |
110 *cur_len -= ssltcp_helper_->remote_hello_message_size(); | |
111 *consumed += ssltcp_helper_->remote_hello_message_size(); | |
112 *cur += ssltcp_helper_->remote_hello_message_size(); | |
113 ssltcp_helper_->set_hello_received(true); | |
114 | |
115 if (!ssltcp_helper_->IsClient()) { | |
116 // Response with a server hello message. | |
117 DoSend(remote_address_, ssltcp_helper_->server_hello_message()); | |
118 ssltcp_helper_->set_hello_sent(true); | |
119 } | |
120 | |
121 return *consumed; | |
122 } | |
123 | |
88 void P2PSocketHostTcpBase::OnConnected(int result) { | 124 void P2PSocketHostTcpBase::OnConnected(int result) { |
89 DCHECK_EQ(state_, STATE_CONNECTING); | 125 DCHECK_EQ(state_, STATE_CONNECTING); |
90 DCHECK_NE(result, net::ERR_IO_PENDING); | 126 DCHECK_NE(result, net::ERR_IO_PENDING); |
91 | 127 |
92 if (result != net::OK) { | 128 if (result != net::OK) { |
93 OnError(); | 129 OnError(); |
94 return; | 130 return; |
95 } | 131 } |
96 | 132 |
97 net::IPEndPoint address; | 133 net::IPEndPoint address; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 return; | 201 return; |
166 } | 202 } |
167 | 203 |
168 if (!(to == remote_address_)) { | 204 if (!(to == remote_address_)) { |
169 // Renderer should use this socket only to send data to |remote_address_|. | 205 // Renderer should use this socket only to send data to |remote_address_|. |
170 NOTREACHED(); | 206 NOTREACHED(); |
171 OnError(); | 207 OnError(); |
172 return; | 208 return; |
173 } | 209 } |
174 | 210 |
211 if (ssltcp_helper_.get() && ssltcp_helper_->IsClient() && | |
212 !ssltcp_helper_->hello_sent()) { | |
213 DoSend(remote_address_, ssltcp_helper_->client_hello_message()); | |
214 ssltcp_helper_->set_hello_sent(true); | |
215 } | |
216 | |
175 if (!connected_) { | 217 if (!connected_) { |
176 P2PSocketHost::StunMessageType type; | 218 P2PSocketHost::StunMessageType type; |
177 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); | 219 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); |
178 if (!stun || type == STUN_DATA_INDICATION) { | 220 if (!stun || type == STUN_DATA_INDICATION) { |
179 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() | 221 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() |
180 << " before STUN binding is finished."; | 222 << " before STUN binding is finished."; |
181 OnError(); | 223 OnError(); |
182 return; | 224 return; |
183 } | 225 } |
184 } | 226 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 pos += consumed; | 307 pos += consumed; |
266 } | 308 } |
267 // We've consumed all complete packets from the buffer; now move any remaining | 309 // We've consumed all complete packets from the buffer; now move any remaining |
268 // bytes to the head of the buffer and set offset to reflect this. | 310 // bytes to the head of the buffer and set offset to reflect this. |
269 if (pos && pos <= read_buffer_->offset()) { | 311 if (pos && pos <= read_buffer_->offset()) { |
270 memmove(head, head + pos, read_buffer_->offset() - pos); | 312 memmove(head, head + pos, read_buffer_->offset() - pos); |
271 read_buffer_->set_offset(read_buffer_->offset() - pos); | 313 read_buffer_->set_offset(read_buffer_->offset() - pos); |
272 } | 314 } |
273 } | 315 } |
274 | 316 |
275 P2PSocketHostTcp::P2PSocketHostTcp(IPC::Sender* message_sender, int id) | 317 P2PSocketHostTcp::P2PSocketHostTcp(IPC::Sender* message_sender, int id, |
276 : P2PSocketHostTcpBase(message_sender, id) { | 318 bool ssl) |
319 : P2PSocketHostTcpBase(message_sender, id, ssl) { | |
277 } | 320 } |
278 | 321 |
279 P2PSocketHostTcp::~P2PSocketHostTcp() { | 322 P2PSocketHostTcp::~P2PSocketHostTcp() { |
280 } | 323 } |
281 | 324 |
282 int P2PSocketHostTcp::ProcessInput(char* input, int input_len) { | 325 int P2PSocketHostTcp::ProcessInput(char* input, int input_len) { |
283 if (input_len < kPacketHeaderSize) | 326 if (input_len < kPacketHeaderSize) |
284 return 0; | 327 return 0; |
285 int packet_size = base::NetToHost16(*reinterpret_cast<uint16*>(input)); | 328 int packet_size = base::NetToHost16(*reinterpret_cast<uint16*>(input)); |
286 if (input_len < packet_size + kPacketHeaderSize) | 329 if (input_len < packet_size + kPacketHeaderSize) |
287 return 0; | 330 return 0; |
288 | 331 |
289 int consumed = kPacketHeaderSize; | 332 int consumed = kPacketHeaderSize; |
290 char* cur = input + consumed; | 333 char* cur = input + consumed; |
334 | |
335 // Handle ssltcp hello message. | |
336 if (ssltcp_helper_.get() && !ssltcp_helper_->hello_received()) { | |
337 return MaybeHandleSslHello(&cur, &packet_size, &consumed); | |
Sergey Ulanov
2013/06/18 20:01:26
I think this should be handled in DidCompleteRead(
| |
338 } | |
339 | |
291 std::vector<char> data(cur, cur + packet_size); | 340 std::vector<char> data(cur, cur + packet_size); |
292 OnPacket(data); | 341 OnPacket(data); |
293 consumed += packet_size; | 342 consumed += packet_size; |
294 return consumed; | 343 return consumed; |
295 } | 344 } |
296 | 345 |
297 void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to, | 346 void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to, |
298 const std::vector<char>& data) { | 347 const std::vector<char>& data) { |
299 int size = kPacketHeaderSize + data.size(); | 348 int size = kPacketHeaderSize + data.size(); |
300 scoped_refptr<net::DrainableIOBuffer> buffer = | 349 scoped_refptr<net::DrainableIOBuffer> buffer = |
301 new net::DrainableIOBuffer(new net::IOBuffer(size), size); | 350 new net::DrainableIOBuffer(new net::IOBuffer(size), size); |
302 *reinterpret_cast<uint16*>(buffer->data()) = base::HostToNet16(data.size()); | 351 *reinterpret_cast<uint16*>(buffer->data()) = base::HostToNet16(data.size()); |
303 memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size()); | 352 memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size()); |
304 | 353 |
305 WriteOrQueue(buffer); | 354 WriteOrQueue(buffer); |
306 } | 355 } |
307 | 356 |
308 // P2PSocketHostStunTcp | 357 // P2PSocketHostStunTcp |
309 P2PSocketHostStunTcp::P2PSocketHostStunTcp(IPC::Sender* message_sender, | 358 P2PSocketHostStunTcp::P2PSocketHostStunTcp(IPC::Sender* message_sender, |
310 int id) | 359 int id, bool ssl) |
311 : P2PSocketHostTcpBase(message_sender, id) { | 360 : P2PSocketHostTcpBase(message_sender, id, ssl) { |
312 } | 361 } |
313 | 362 |
314 P2PSocketHostStunTcp::~P2PSocketHostStunTcp() { | 363 P2PSocketHostStunTcp::~P2PSocketHostStunTcp() { |
315 } | 364 } |
316 | 365 |
317 int P2PSocketHostStunTcp::ProcessInput(char* input, int input_len) { | 366 int P2PSocketHostStunTcp::ProcessInput(char* input, int input_len) { |
318 if (input_len < kPacketHeaderSize + kPacketLengthOffset) | 367 int consumed = 0; |
319 return 0; | 368 char* cur = input; |
369 int cur_len = input_len; | |
370 int pad_bytes; | |
320 | 371 |
321 int pad_bytes; | 372 // Handle ssltcp hello message if not received yet. |
322 int packet_size = GetExpectedPacketSize( | 373 if (ssltcp_helper_.get() && !ssltcp_helper_->hello_received()) { |
323 input, input_len, &pad_bytes); | 374 return MaybeHandleSslHello(&cur, &cur_len, &consumed); |
375 } | |
324 | 376 |
325 if (input_len < packet_size + pad_bytes) | 377 if (cur_len < kPacketHeaderSize + kPacketLengthOffset) |
326 return 0; | 378 return consumed; |
379 | |
380 int packet_size = GetExpectedPacketSize(cur, cur_len, &pad_bytes); | |
381 | |
382 if (cur_len < packet_size + pad_bytes) | |
383 return consumed; | |
327 | 384 |
328 // We have a complete packet. Read through it. | 385 // We have a complete packet. Read through it. |
329 int consumed = 0; | |
330 char* cur = input; | |
331 std::vector<char> data(cur, cur + packet_size); | 386 std::vector<char> data(cur, cur + packet_size); |
332 OnPacket(data); | 387 OnPacket(data); |
333 consumed += packet_size; | 388 consumed += packet_size; |
334 consumed += pad_bytes; | 389 consumed += pad_bytes; |
335 return consumed; | 390 return consumed; |
336 } | 391 } |
337 | 392 |
338 void P2PSocketHostStunTcp::DoSend(const net::IPEndPoint& to, | 393 void P2PSocketHostStunTcp::DoSend(const net::IPEndPoint& to, |
339 const std::vector<char>& data) { | 394 const std::vector<char>& data) { |
340 // Each packet is expected to have header (STUN/TURN ChannelData), where | 395 // Each packet is expected to have header (STUN/TURN ChannelData), where |
341 // header contains message type and and length of message. | 396 // header contains message type and and length of message. |
342 if (data.size() < kPacketHeaderSize + kPacketLengthOffset) { | 397 if (data.size() < kPacketHeaderSize + kPacketLengthOffset) { |
343 NOTREACHED(); | 398 NOTREACHED(); |
344 OnError(); | 399 OnError(); |
345 return; | 400 return; |
346 } | 401 } |
347 | 402 |
348 int pad_bytes; | 403 int pad_bytes; |
349 size_t expected_len = GetExpectedPacketSize( | 404 size_t expected_len = GetExpectedPacketSize( |
350 &data[0], data.size(), &pad_bytes); | 405 &data[0], data.size(), &pad_bytes); |
351 | 406 |
407 if (ssltcp_helper_.get() && !ssltcp_helper_->hello_sent()) { | |
408 expected_len = ssltcp_helper_->hello_message_size(); | |
Sergey Ulanov
2013/06/18 20:01:26
Why do we need this here? P2PSocketHostTcpBase::Se
| |
409 pad_bytes = 0; | |
410 } | |
411 | |
352 // Accepts only complete STUN/TURN packets. | 412 // Accepts only complete STUN/TURN packets. |
353 if (data.size() != expected_len) { | 413 if (data.size() != expected_len) { |
354 NOTREACHED(); | 414 NOTREACHED(); |
355 OnError(); | 415 OnError(); |
356 return; | 416 return; |
357 } | 417 } |
358 | 418 |
359 // Add any pad bytes to the total size. | 419 // Add any pad bytes to the total size. |
360 int size = data.size() + pad_bytes; | 420 int size = data.size() + pad_bytes; |
361 | 421 |
(...skipping 26 matching lines...) Expand all Loading... | |
388 } else { | 448 } else { |
389 packet_size += kTurnChannelDataHeaderSize; | 449 packet_size += kTurnChannelDataHeaderSize; |
390 // Calculate any padding if present. | 450 // Calculate any padding if present. |
391 if (packet_size % 4) | 451 if (packet_size % 4) |
392 *pad_bytes = 4 - packet_size % 4; | 452 *pad_bytes = 4 - packet_size % 4; |
393 } | 453 } |
394 return packet_size; | 454 return packet_size; |
395 } | 455 } |
396 | 456 |
397 } // namespace content | 457 } // namespace content |
OLD | NEW |