Chromium Code Reviews| 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 |