Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: content/browser/renderer_host/p2p/socket_host_tcp.cc

Issue 16516003: SSLTCP (pseudo-SSL with fake handshake and unencrypted data) support for p2p socket. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698