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