socket_host_tcp.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 3// found in the LICENSE file. 4 5#include "content/browser/renderer_host/p2p/socket_host_tcp.h" 6 7#include "base/sys_byteorder.h" 8#include "content/common/p2p_messages.h" 9#include "ipc/ipc_sender.h" 10#include "jingle/glue/fake_ssl_client_socket.h" 11#include "jingle/glue/proxy_resolving_client_socket.h" 12#include "net/base/io_buffer.h" 13#include "net/base/net_errors.h" 14#include "net/base/net_util.h" 15#include "net/socket/client_socket_factory.h" 16#include "net/socket/client_socket_handle.h" 17#include "net/socket/ssl_client_socket.h" 18#include "net/socket/tcp_client_socket.h" 19#include "net/url_request/url_request_context.h" 20#include "net/url_request/url_request_context_getter.h" 21#include "third_party/webrtc/base/asyncpacketsocket.h" 22 23namespace { 24 25typedef uint16 PacketLength; 26const int kPacketHeaderSize = sizeof(PacketLength); 27const int kReadBufferSize = 4096; 28const int kPacketLengthOffset = 2; 29const int kTurnChannelDataHeaderSize = 4; 30const int kRecvSocketBufferSize = 128 * 1024; 31const int kSendSocketBufferSize = 128 * 1024; 32 33bool IsTlsClientSocket(content::P2PSocketType type) { 34 return (type == content::P2P_SOCKET_STUN_TLS_CLIENT || 35 type == content::P2P_SOCKET_TLS_CLIENT); 36} 37 38bool IsPseudoTlsClientSocket(content::P2PSocketType type) { 39 return (type == content::P2P_SOCKET_SSLTCP_CLIENT || 40 type == content::P2P_SOCKET_STUN_SSLTCP_CLIENT); 41} 42 43} // namespace 44 45namespace content { 46 47P2PSocketHostTcpBase::P2PSocketHostTcpBase( 48 IPC::Sender* message_sender, 49 int socket_id, 50 P2PSocketType type, 51 net::URLRequestContextGetter* url_context) 52 : P2PSocketHost(message_sender, socket_id), 53 write_pending_(false), 54 connected_(false), 55 type_(type), 56 url_context_(url_context) { 57} 58 59P2PSocketHostTcpBase::~P2PSocketHostTcpBase() { 60 if (state_ == STATE_OPEN) { 61 DCHECK(socket_.get()); 62 socket_.reset(); 63 } 64} 65 66bool P2PSocketHostTcpBase::InitAccepted(const net::IPEndPoint& remote_address, 67 net::StreamSocket* socket) { 68 DCHECK(socket); 69 DCHECK_EQ(state_, STATE_UNINITIALIZED); 70 71 remote_address_.ip_address = remote_address; 72 // TODO(ronghuawu): Add FakeSSLServerSocket. 73 socket_.reset(socket); 74 state_ = STATE_OPEN; 75 DoRead(); 76 return state_ != STATE_ERROR; 77} 78 79bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address, 80 const P2PHostAndIPEndPoint& remote_address) { 81 DCHECK_EQ(state_, STATE_UNINITIALIZED); 82 83 remote_address_ = remote_address; 84 state_ = STATE_CONNECTING; 85 86 net::HostPortPair dest_host_port_pair; 87 // If there is no resolved address, let's try with domain name, assuming 88 // socket layer will do the DNS resolve. 89 if (remote_address.ip_address.address().empty()) { 90 DCHECK(!remote_address.hostname.empty()); 91 dest_host_port_pair = net::HostPortPair::FromString( 92 remote_address.hostname); 93 } else { 94 dest_host_port_pair = net::HostPortPair::FromIPEndPoint( 95 remote_address.ip_address); 96 } 97 98 // TODO(mallinath) - We are ignoring local_address altogether. We should 99 // find a way to inject this into ProxyResolvingClientSocket. This could be 100 // a problem on multi-homed host. 101 102 // The default SSLConfig is good enough for us for now. 103 const net::SSLConfig ssl_config; 104 socket_.reset(new jingle_glue::ProxyResolvingClientSocket( 105 NULL, // Default socket pool provided by the net::Proxy. 106 url_context_, 107 ssl_config, 108 dest_host_port_pair)); 109 110 int status = socket_->Connect( 111 base::Bind(&P2PSocketHostTcpBase::OnConnected, 112 base::Unretained(this))); 113 if (status != net::ERR_IO_PENDING) { 114 // We defer execution of ProcessConnectDone instead of calling it 115 // directly here as the caller may not expect an error/close to 116 // happen here. This is okay, as from the caller's point of view, 117 // the connect always happens asynchronously. 118 base::MessageLoop* message_loop = base::MessageLoop::current(); 119 CHECK(message_loop); 120 message_loop->PostTask( 121 FROM_HERE, 122 base::Bind(&P2PSocketHostTcpBase::OnConnected, 123 base::Unretained(this), status)); 124 } 125 126 return state_ != STATE_ERROR; 127} 128 129void P2PSocketHostTcpBase::OnError() { 130 socket_.reset(); 131 132 if (state_ == STATE_UNINITIALIZED || state_ == STATE_CONNECTING || 133 state_ == STATE_TLS_CONNECTING || state_ == STATE_OPEN) { 134 message_sender_->Send(new P2PMsg_OnError(id_)); 135 } 136 137 state_ = STATE_ERROR; 138} 139 140void P2PSocketHostTcpBase::OnConnected(int result) { 141 DCHECK_EQ(state_, STATE_CONNECTING); 142 DCHECK_NE(result, net::ERR_IO_PENDING); 143 144 if (result != net::OK) { 145 OnError(); 146 return; 147 } 148 149 if (IsTlsClientSocket(type_)) { 150 state_ = STATE_TLS_CONNECTING; 151 StartTls(); 152 } else if (IsPseudoTlsClientSocket(type_)) { 153 scoped_ptr<net::StreamSocket> transport_socket = socket_.Pass(); 154 socket_.reset( 155 new jingle_glue::FakeSSLClientSocket(transport_socket.Pass())); 156 state_ = STATE_TLS_CONNECTING; 157 int status = socket_->Connect( 158 base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone, 159 base::Unretained(this))); 160 if (status != net::ERR_IO_PENDING) { 161 ProcessTlsSslConnectDone(status); 162 } 163 } else { 164 // If we are not doing TLS, we are ready to send data now. 165 // In case of TLS, SignalConnect will be sent only after TLS handshake is 166 // successfull. So no buffering will be done at socket handlers if any 167 // packets sent before that by the application. 168 OnOpen(); 169 } 170} 171 172void P2PSocketHostTcpBase::StartTls() { 173 DCHECK_EQ(state_, STATE_TLS_CONNECTING); 174 DCHECK(socket_.get()); 175 176 scoped_ptr<net::ClientSocketHandle> socket_handle( 177 new net::ClientSocketHandle()); 178 socket_handle->SetSocket(socket_.Pass()); 179 180 net::SSLClientSocketContext context; 181 context.cert_verifier = url_context_->GetURLRequestContext()->cert_verifier(); 182 context.transport_security_state = 183 url_context_->GetURLRequestContext()->transport_security_state(); 184 DCHECK(context.transport_security_state); 185 186 // Default ssl config. 187 const net::SSLConfig ssl_config; 188 net::HostPortPair dest_host_port_pair; 189 if (remote_address_.ip_address.address().empty()) { 190 DCHECK(!remote_address_.hostname.empty()); 191 dest_host_port_pair = net::HostPortPair::FromString( 192 remote_address_.hostname); 193 } else { 194 dest_host_port_pair = net::HostPortPair::FromIPEndPoint( 195 remote_address_.ip_address); 196 if (!remote_address_.hostname.empty()) 197 dest_host_port_pair.set_host(remote_address_.hostname); 198 } 199 200 net::ClientSocketFactory* socket_factory = 201 net::ClientSocketFactory::GetDefaultFactory(); 202 DCHECK(socket_factory); 203 204 socket_ = socket_factory->CreateSSLClientSocket( 205 socket_handle.Pass(), dest_host_port_pair, ssl_config, context); 206 int status = socket_->Connect( 207 base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone, 208 base::Unretained(this))); 209 if (status != net::ERR_IO_PENDING) { 210 ProcessTlsSslConnectDone(status); 211 } 212} 213 214void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) { 215 DCHECK_NE(status, net::ERR_IO_PENDING); 216 DCHECK_EQ(state_, STATE_TLS_CONNECTING); 217 if (status != net::OK) { 218 OnError(); 219 return; 220 } 221 OnOpen(); 222} 223 224void P2PSocketHostTcpBase::OnOpen() { 225 state_ = STATE_OPEN; 226 // Setting socket send and receive buffer size. 227 if (net::OK != socket_->SetReceiveBufferSize(kRecvSocketBufferSize)) { 228 LOG(WARNING) << "Failed to set socket receive buffer size to " 229 << kRecvSocketBufferSize; 230 } 231 232 if (net::OK != socket_->SetSendBufferSize(kSendSocketBufferSize)) { 233 LOG(WARNING) << "Failed to set socket send buffer size to " 234 << kSendSocketBufferSize; 235 } 236 237 DoSendSocketCreateMsg(); 238 DoRead(); 239} 240 241void P2PSocketHostTcpBase::DoSendSocketCreateMsg() { 242 DCHECK(socket_.get()); 243 244 net::IPEndPoint local_address; 245 int result = socket_->GetLocalAddress(&local_address); 246 if (result < 0) { 247 LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get local" 248 << " address: " << result; 249 OnError(); 250 return; 251 } 252 253 VLOG(1) << "Local address: " << local_address.ToString(); 254 255 net::IPEndPoint remote_address; 256 result = socket_->GetPeerAddress(&remote_address); 257 if (result < 0) { 258 LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get peer" 259 << " address: " << result; 260 OnError(); 261 return; 262 } 263 VLOG(1) << "Remote address: " << remote_address.ToString(); 264 if (remote_address_.ip_address.address().empty()) { 265 // Save |remote_address| if address is empty. 266 remote_address_.ip_address = remote_address; 267 } 268 269 // If we are not doing TLS, we are ready to send data now. 270 // In case of TLS SignalConnect will be sent only after TLS handshake is 271 // successfull. So no buffering will be done at socket handlers if any 272 // packets sent before that by the application. 273 message_sender_->Send(new P2PMsg_OnSocketCreated( 274 id_, local_address, remote_address)); 275} 276 277void P2PSocketHostTcpBase::DoRead() { 278 int result; 279 do { 280 if (!read_buffer_.get()) { 281 read_buffer_ = new net::GrowableIOBuffer(); 282 read_buffer_->SetCapacity(kReadBufferSize); 283 } else if (read_buffer_->RemainingCapacity() < kReadBufferSize) { 284 // Make sure that we always have at least kReadBufferSize of 285 // remaining capacity in the read buffer. Normally all packets 286 // are smaller than kReadBufferSize, so this is not really 287 // required. 288 read_buffer_->SetCapacity(read_buffer_->capacity() + kReadBufferSize - 289 read_buffer_->RemainingCapacity()); 290 } 291 result = socket_->Read( 292 read_buffer_.get(), 293 read_buffer_->RemainingCapacity(), 294 base::Bind(&P2PSocketHostTcp::OnRead, base::Unretained(this))); 295 DidCompleteRead(result); 296 } while (result > 0); 297} 298 299void P2PSocketHostTcpBase::OnRead(int result) { 300 DidCompleteRead(result); 301 if (state_ == STATE_OPEN) { 302 DoRead(); 303 } 304} 305 306void P2PSocketHostTcpBase::OnPacket(const std::vector<char>& data) { 307 if (!connected_) { 308 P2PSocketHost::StunMessageType type; 309 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); 310 if (stun && IsRequestOrResponse(type)) { 311 connected_ = true; 312 } else if (!stun || type == STUN_DATA_INDICATION) { 313 LOG(ERROR) << "Received unexpected data packet from " 314 << remote_address_.ip_address.ToString() 315 << " before STUN binding is finished. " 316 << "Terminating connection."; 317 OnError(); 318 return; 319 } 320 } 321 322 message_sender_->Send(new P2PMsg_OnDataReceived( 323 id_, remote_address_.ip_address, data, base::TimeTicks::Now())); 324 325 if (dump_incoming_rtp_packet_) 326 DumpRtpPacket(&data[0], data.size(), true); 327} 328 329// Note: dscp is not actually used on TCP sockets as this point, 330// but may be honored in the future. 331void P2PSocketHostTcpBase::Send(const net::IPEndPoint& to, 332 const std::vector<char>& data, 333 const rtc::PacketOptions& options, 334 uint64 packet_id) { 335 if (!socket_) { 336 // The Send message may be sent after the an OnError message was 337 // sent by hasn't been processed the renderer. 338 return; 339 } 340 341 if (!(to == remote_address_.ip_address)) { 342 // Renderer should use this socket only to send data to |remote_address_|. 343 NOTREACHED(); 344 OnError(); 345 return; 346 } 347 348 if (!connected_) { 349 P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType(); 350 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); 351 if (!stun || type == STUN_DATA_INDICATION) { 352 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() 353 << " before STUN binding is finished."; 354 OnError(); 355 return; 356 } 357 } 358 359 DoSend(to, data, options); 360} 361 362void P2PSocketHostTcpBase::WriteOrQueue( 363 scoped_refptr<net::DrainableIOBuffer>& buffer) { 364 if (write_buffer_.get()) { 365 write_queue_.push(buffer); 366 return; 367 } 368 369 write_buffer_ = buffer; 370 DoWrite(); 371} 372 373void P2PSocketHostTcpBase::DoWrite() { 374 while (write_buffer_.get() && state_ == STATE_OPEN && !write_pending_) { 375 int result = socket_->Write( 376 write_buffer_.get(), 377 write_buffer_->BytesRemaining(), 378 base::Bind(&P2PSocketHostTcp::OnWritten, base::Unretained(this))); 379 HandleWriteResult(result); 380 } 381} 382 383void P2PSocketHostTcpBase::OnWritten(int result) { 384 DCHECK(write_pending_); 385 DCHECK_NE(result, net::ERR_IO_PENDING); 386 387 write_pending_ = false; 388 HandleWriteResult(result); 389 DoWrite(); 390} 391 392void P2PSocketHostTcpBase::HandleWriteResult(int result) { 393 DCHECK(write_buffer_.get()); 394 if (result >= 0) { 395 write_buffer_->DidConsume(result); 396 if (write_buffer_->BytesRemaining() == 0) { 397 message_sender_->Send(new P2PMsg_OnSendComplete(id_)); 398 if (write_queue_.empty()) { 399 write_buffer_ = NULL; 400 } else { 401 write_buffer_ = write_queue_.front(); 402 write_queue_.pop(); 403 } 404 } 405 } else if (result == net::ERR_IO_PENDING) { 406 write_pending_ = true; 407 } else { 408 LOG(ERROR) << "Error when sending data in TCP socket: " << result; 409 OnError(); 410 } 411} 412 413P2PSocketHost* P2PSocketHostTcpBase::AcceptIncomingTcpConnection( 414 const net::IPEndPoint& remote_address, int id) { 415 NOTREACHED(); 416 OnError(); 417 return NULL; 418} 419 420void P2PSocketHostTcpBase::DidCompleteRead(int result) { 421 DCHECK_EQ(state_, STATE_OPEN); 422 423 if (result == net::ERR_IO_PENDING) { 424 return; 425 } else if (result < 0) { 426 LOG(ERROR) << "Error when reading from TCP socket: " << result; 427 OnError(); 428 return; 429 } 430 431 read_buffer_->set_offset(read_buffer_->offset() + result); 432 char* head = read_buffer_->StartOfBuffer(); // Purely a convenience. 433 int pos = 0; 434 while (pos <= read_buffer_->offset() && state_ == STATE_OPEN) { 435 int consumed = ProcessInput(head + pos, read_buffer_->offset() - pos); 436 if (!consumed) 437 break; 438 pos += consumed; 439 } 440 // We've consumed all complete packets from the buffer; now move any remaining 441 // bytes to the head of the buffer and set offset to reflect this. 442 if (pos && pos <= read_buffer_->offset()) { 443 memmove(head, head + pos, read_buffer_->offset() - pos); 444 read_buffer_->set_offset(read_buffer_->offset() - pos); 445 } 446} 447 448bool P2PSocketHostTcpBase::SetOption(P2PSocketOption option, int value) { 449 DCHECK_EQ(STATE_OPEN, state_); 450 switch (option) { 451 case P2P_SOCKET_OPT_RCVBUF: 452 return socket_->SetReceiveBufferSize(value) == net::OK; 453 case P2P_SOCKET_OPT_SNDBUF: 454 return socket_->SetSendBufferSize(value) == net::OK; 455 case P2P_SOCKET_OPT_DSCP: 456 return false; // For TCP sockets DSCP setting is not available. 457 default: 458 NOTREACHED(); 459 return false; 460 } 461} 462 463P2PSocketHostTcp::P2PSocketHostTcp(IPC::Sender* message_sender, 464 int socket_id, 465 P2PSocketType type, 466 net::URLRequestContextGetter* url_context) 467 : P2PSocketHostTcpBase(message_sender, socket_id, type, url_context) { 468 DCHECK(type == P2P_SOCKET_TCP_CLIENT || 469 type == P2P_SOCKET_SSLTCP_CLIENT || 470 type == P2P_SOCKET_TLS_CLIENT); 471} 472 473P2PSocketHostTcp::~P2PSocketHostTcp() { 474} 475 476int P2PSocketHostTcp::ProcessInput(char* input, int input_len) { 477 if (input_len < kPacketHeaderSize) 478 return 0; 479 int packet_size = base::NetToHost16(*reinterpret_cast<uint16*>(input)); 480 if (input_len < packet_size + kPacketHeaderSize) 481 return 0; 482 483 int consumed = kPacketHeaderSize; 484 char* cur = input + consumed; 485 std::vector<char> data(cur, cur + packet_size); 486 OnPacket(data); 487 consumed += packet_size; 488 return consumed; 489} 490 491void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to, 492 const std::vector<char>& data, 493 const rtc::PacketOptions& options) { 494 int size = kPacketHeaderSize + data.size(); 495 scoped_refptr<net::DrainableIOBuffer> buffer = 496 new net::DrainableIOBuffer(new net::IOBuffer(size), size); 497 *reinterpret_cast<uint16*>(buffer->data()) = base::HostToNet16(data.size()); 498 memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size()); 499 500 packet_processing_helpers::ApplyPacketOptions( 501 buffer->data() + kPacketHeaderSize, 502 buffer->BytesRemaining() - kPacketHeaderSize, 503 options, 0); 504 505 WriteOrQueue(buffer); 506} 507 508// P2PSocketHostStunTcp 509P2PSocketHostStunTcp::P2PSocketHostStunTcp( 510 IPC::Sender* message_sender, 511 int socket_id, 512 P2PSocketType type, 513 net::URLRequestContextGetter* url_context) 514 : P2PSocketHostTcpBase(message_sender, socket_id, type, url_context) { 515 DCHECK(type == P2P_SOCKET_STUN_TCP_CLIENT || 516 type == P2P_SOCKET_STUN_SSLTCP_CLIENT || 517 type == P2P_SOCKET_STUN_TLS_CLIENT); 518} 519 520P2PSocketHostStunTcp::~P2PSocketHostStunTcp() { 521} 522 523int P2PSocketHostStunTcp::ProcessInput(char* input, int input_len) { 524 if (input_len < kPacketHeaderSize + kPacketLengthOffset) 525 return 0; 526 527 int pad_bytes; 528 int packet_size = GetExpectedPacketSize( 529 input, input_len, &pad_bytes); 530 531 if (input_len < packet_size + pad_bytes) 532 return 0; 533 534 // We have a complete packet. Read through it. 535 int consumed = 0; 536 char* cur = input; 537 std::vector<char> data(cur, cur + packet_size); 538 OnPacket(data); 539 consumed += packet_size; 540 consumed += pad_bytes; 541 return consumed; 542} 543 544void P2PSocketHostStunTcp::DoSend(const net::IPEndPoint& to, 545 const std::vector<char>& data, 546 const rtc::PacketOptions& options) { 547 // Each packet is expected to have header (STUN/TURN ChannelData), where 548 // header contains message type and and length of message. 549 if (data.size() < kPacketHeaderSize + kPacketLengthOffset) { 550 NOTREACHED(); 551 OnError(); 552 return; 553 } 554 555 int pad_bytes; 556 size_t expected_len = GetExpectedPacketSize( 557 &data[0], data.size(), &pad_bytes); 558 559 // Accepts only complete STUN/TURN packets. 560 if (data.size() != expected_len) { 561 NOTREACHED(); 562 OnError(); 563 return; 564 } 565 566 // Add any pad bytes to the total size. 567 int size = data.size() + pad_bytes; 568 569 scoped_refptr<net::DrainableIOBuffer> buffer = 570 new net::DrainableIOBuffer(new net::IOBuffer(size), size); 571 memcpy(buffer->data(), &data[0], data.size()); 572 573 packet_processing_helpers::ApplyPacketOptions( 574 buffer->data(), data.size(), options, 0); 575 576 if (pad_bytes) { 577 char padding[4] = {0}; 578 DCHECK_LE(pad_bytes, 4); 579 memcpy(buffer->data() + data.size(), padding, pad_bytes); 580 } 581 WriteOrQueue(buffer); 582 583 if (dump_outgoing_rtp_packet_) 584 DumpRtpPacket(buffer->data(), data.size(), false); 585} 586 587int P2PSocketHostStunTcp::GetExpectedPacketSize( 588 const char* data, int len, int* pad_bytes) { 589 DCHECK_LE(kTurnChannelDataHeaderSize, len); 590 // Both stun and turn had length at offset 2. 591 int packet_size = base::NetToHost16(*reinterpret_cast<const uint16*>( 592 data + kPacketLengthOffset)); 593 594 // Get packet type (STUN or TURN). 595 uint16 msg_type = base::NetToHost16(*reinterpret_cast<const uint16*>(data)); 596 597 *pad_bytes = 0; 598 // Add heder length to packet length. 599 if ((msg_type & 0xC000) == 0) { 600 packet_size += kStunHeaderSize; 601 } else { 602 packet_size += kTurnChannelDataHeaderSize; 603 // Calculate any padding if present. 604 if (packet_size % 4) 605 *pad_bytes = 4 - packet_size % 4; 606 } 607 return packet_size; 608} 609 610} // namespace content 611