15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/p2p/socket_host_tcp.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/p2p_messages.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_sender.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "jingle/glue/fake_ssl_client_socket.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "jingle/glue/proxy_resolving_client_socket.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 15c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "net/socket/client_socket_factory.h" 16c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "net/socket/client_socket_handle.h" 17c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "net/socket/ssl_client_socket.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h" 19c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "net/url_request/url_request_context.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/url_request/url_request_context_getter.h" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/webrtc/base/asyncpacketsocket.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)typedef uint16 PacketLength; 26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const int kPacketHeaderSize = sizeof(PacketLength); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kReadBufferSize = 4096; 28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const int kPacketLengthOffset = 2; 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const int kTurnChannelDataHeaderSize = 4; 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const int kRecvSocketBufferSize = 128 * 1024; 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const int kSendSocketBufferSize = 128 * 1024; 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 33c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochbool IsTlsClientSocket(content::P2PSocketType type) { 34c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return (type == content::P2P_SOCKET_STUN_TLS_CLIENT || 35c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch type == content::P2P_SOCKET_TLS_CLIENT); 36c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 37c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 38c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochbool IsPseudoTlsClientSocket(content::P2PSocketType type) { 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return (type == content::P2P_SOCKET_SSLTCP_CLIENT || 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch type == content::P2P_SOCKET_STUN_SSLTCP_CLIENT); 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochP2PSocketHostTcpBase::P2PSocketHostTcpBase( 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) IPC::Sender* message_sender, 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int socket_id, 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) P2PSocketType type, 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::URLRequestContextGetter* url_context) 52ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch : P2PSocketHost(message_sender, socket_id, P2PSocketHost::TCP), 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_pending_(false), 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch connected_(false), 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch type_(type), 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_context_(url_context) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)P2PSocketHostTcpBase::~P2PSocketHostTcpBase() { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == STATE_OPEN) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket_.get()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_.reset(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool P2PSocketHostTcpBase::InitAccepted(const net::IPEndPoint& remote_address, 67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) net::StreamSocket* socket) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, STATE_UNINITIALIZED); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) remote_address_.ip_address = remote_address; 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(ronghuawu): Add FakeSSLServerSocket. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_.reset(socket); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = STATE_OPEN; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoRead(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state_ != STATE_ERROR; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address, 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const P2PHostAndIPEndPoint& remote_address) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, STATE_UNINITIALIZED); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remote_address_ = remote_address; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = STATE_CONNECTING; 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::HostPortPair dest_host_port_pair; 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If there is no resolved address, let's try with domain name, assuming 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // socket layer will do the DNS resolve. 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (remote_address.ip_address.address().empty()) { 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!remote_address.hostname.empty()); 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dest_host_port_pair = net::HostPortPair::FromString( 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch remote_address.hostname); 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch dest_host_port_pair = net::HostPortPair::FromIPEndPoint( 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch remote_address.ip_address); 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(mallinath) - We are ignoring local_address altogether. We should 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // find a way to inject this into ProxyResolvingClientSocket. This could be 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // a problem on multi-homed host. 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // The default SSLConfig is good enough for us for now. 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const net::SSLConfig ssl_config; 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch socket_.reset(new jingle_glue::ProxyResolvingClientSocket( 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, // Default socket pool provided by the net::Proxy. 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch url_context_, 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ssl_config, 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch dest_host_port_pair)); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int status = socket_->Connect( 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&P2PSocketHostTcpBase::OnConnected, 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this))); 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (status != net::ERR_IO_PENDING) { 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We defer execution of ProcessConnectDone instead of calling it 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // directly here as the caller may not expect an error/close to 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // happen here. This is okay, as from the caller's point of view, 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // the connect always happens asynchronously. 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoop* message_loop = base::MessageLoop::current(); 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK(message_loop); 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch message_loop->PostTask( 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FROM_HERE, 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&P2PSocketHostTcpBase::OnConnected, 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this), status)); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state_ != STATE_ERROR; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::OnError() { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_.reset(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == STATE_UNINITIALIZED || state_ == STATE_CONNECTING || 133c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch state_ == STATE_TLS_CONNECTING || state_ == STATE_OPEN) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_sender_->Send(new P2PMsg_OnError(id_)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = STATE_ERROR; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::OnConnected(int result) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, STATE_CONNECTING); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(result, net::ERR_IO_PENDING); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != net::OK) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnError(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (IsTlsClientSocket(type_)) { 150c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch state_ = STATE_TLS_CONNECTING; 151c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch StartTls(); 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if (IsPseudoTlsClientSocket(type_)) { 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<net::StreamSocket> transport_socket = socket_.Pass(); 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) socket_.reset( 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) new jingle_glue::FakeSSLClientSocket(transport_socket.Pass())); 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) state_ = STATE_TLS_CONNECTING; 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int status = socket_->Connect( 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone, 15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Unretained(this))); 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (status != net::ERR_IO_PENDING) { 16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProcessTlsSslConnectDone(status); 162c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 164c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // If we are not doing TLS, we are ready to send data now. 165c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // In case of TLS, SignalConnect will be sent only after TLS handshake is 166c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // successfull. So no buffering will be done at socket handlers if any 167c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // packets sent before that by the application. 16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) OnOpen(); 169c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 170c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 171c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 172c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid P2PSocketHostTcpBase::StartTls() { 173c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK_EQ(state_, STATE_TLS_CONNECTING); 174c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK(socket_.get()); 175c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 176c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch scoped_ptr<net::ClientSocketHandle> socket_handle( 177c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch new net::ClientSocketHandle()); 1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) socket_handle->SetSocket(socket_.Pass()); 179c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 180c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch net::SSLClientSocketContext context; 181c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch context.cert_verifier = url_context_->GetURLRequestContext()->cert_verifier(); 182c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch context.transport_security_state = 183c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch url_context_->GetURLRequestContext()->transport_security_state(); 184c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK(context.transport_security_state); 185c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 186c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Default ssl config. 187c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch const net::SSLConfig ssl_config; 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::HostPortPair dest_host_port_pair; 1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Calling net::HostPortPair::FromIPEndPoint will crash if the IP address is 1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // empty. 1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!remote_address_.ip_address.address().empty()) { 1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) net::HostPortPair::FromIPEndPoint(remote_address_.ip_address); 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dest_host_port_pair.set_port(remote_address_.ip_address.port()); 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!remote_address_.hostname.empty()) 1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) dest_host_port_pair.set_host(remote_address_.hostname); 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 200c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch net::ClientSocketFactory* socket_factory = 201c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch net::ClientSocketFactory::GetDefaultFactory(); 202c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK(socket_factory); 203c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) socket_ = socket_factory->CreateSSLClientSocket( 2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) socket_handle.Pass(), dest_host_port_pair, ssl_config, context); 206c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch int status = socket_->Connect( 20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone, 208c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base::Unretained(this))); 209c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (status != net::ERR_IO_PENDING) { 21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProcessTlsSslConnectDone(status); 211c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 212c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 213c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) { 215c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK_NE(status, net::ERR_IO_PENDING); 216c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK_EQ(state_, STATE_TLS_CONNECTING); 217c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (status != net::OK) { 218c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch OnError(); 219c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch return; 220c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) OnOpen(); 22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 223c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void P2PSocketHostTcpBase::OnOpen() { 225c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch state_ = STATE_OPEN; 226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Setting socket send and receive buffer size. 227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (net::OK != socket_->SetReceiveBufferSize(kRecvSocketBufferSize)) { 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(WARNING) << "Failed to set socket receive buffer size to " 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << kRecvSocketBufferSize; 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (net::OK != socket_->SetSendBufferSize(kSendSocketBufferSize)) { 233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(WARNING) << "Failed to set socket send buffer size to " 234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << kSendSocketBufferSize; 235a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 237c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DoSendSocketCreateMsg(); 238c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DoRead(); 239c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch} 240c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 241c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdochvoid P2PSocketHostTcpBase::DoSendSocketCreateMsg() { 242c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK(socket_.get()); 243c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::IPEndPoint local_address; 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int result = socket_->GetLocalAddress(&local_address); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 247c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get local" 248c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch << " address: " << result; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnError(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(1) << "Local address: " << local_address.ToString(); 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::IPEndPoint remote_address; 256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result = socket_->GetPeerAddress(&remote_address); 257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result < 0) { 258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get peer" 259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << " address: " << result; 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch OnError(); 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(1) << "Remote address: " << remote_address.ToString(); 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (remote_address_.ip_address.address().empty()) { 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Save |remote_address| if address is empty. 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch remote_address_.ip_address = remote_address; 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 268c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 269c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // If we are not doing TLS, we are ready to send data now. 270c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // In case of TLS SignalConnect will be sent only after TLS handshake is 271c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // successfull. So no buffering will be done at socket handlers if any 272c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // packets sent before that by the application. 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch message_sender_->Send(new P2PMsg_OnSocketCreated( 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch id_, local_address, remote_address)); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::DoRead() { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!read_buffer_.get()) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = new net::GrowableIOBuffer(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_->SetCapacity(kReadBufferSize); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (read_buffer_->RemainingCapacity() < kReadBufferSize) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that we always have at least kReadBufferSize of 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // remaining capacity in the read buffer. Normally all packets 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are smaller than kReadBufferSize, so this is not really 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // required. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_->SetCapacity(read_buffer_->capacity() + kReadBufferSize - 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_->RemainingCapacity()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result = socket_->Read( 292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) read_buffer_.get(), 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) read_buffer_->RemainingCapacity(), 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&P2PSocketHostTcp::OnRead, base::Unretained(this))); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DidCompleteRead(result); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (result > 0); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::OnRead(int result) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DidCompleteRead(result); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == STATE_OPEN) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoRead(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::OnPacket(const std::vector<char>& data) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connected_) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P2PSocketHost::StunMessageType type; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stun && IsRequestOrResponse(type)) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connected_ = true; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!stun || type == STUN_DATA_INDICATION) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Received unexpected data packet from " 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << remote_address_.ip_address.ToString() 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " before STUN binding is finished. " 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Terminating connection."; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnError(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_sender_->Send(new P2PMsg_OnDataReceived( 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) id_, remote_address_.ip_address, data, base::TimeTicks::Now())); 32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (dump_incoming_rtp_packet_) 32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DumpRtpPacket(&data[0], data.size(), true); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Note: dscp is not actually used on TCP sockets as this point, 3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// but may be honored in the future. 331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::Send(const net::IPEndPoint& to, 3328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::vector<char>& data, 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const rtc::PacketOptions& options, 3348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) uint64 packet_id) { 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!socket_) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Send message may be sent after the an OnError message was 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sent by hasn't been processed the renderer. 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!(to == remote_address_.ip_address)) { 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Renderer should use this socket only to send data to |remote_address_|. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnError(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connected_) { 3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType(); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!stun || type == STUN_DATA_INDICATION) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " before STUN binding is finished."; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnError(); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DoSend(to, data, options); 360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::WriteOrQueue( 363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<net::DrainableIOBuffer>& buffer) { 364ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch IncrementTotalSentPackets(); 365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (write_buffer_.get()) { 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_queue_.push(buffer); 367ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch IncrementDelayedPackets(); 368ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch IncrementDelayedBytes(buffer->size()); 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_buffer_ = buffer; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoWrite(); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::DoWrite() { 377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (write_buffer_.get() && state_ == STATE_OPEN && !write_pending_) { 378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int result = socket_->Write( 379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) write_buffer_.get(), 380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) write_buffer_->BytesRemaining(), 381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&P2PSocketHostTcp::OnWritten, base::Unretained(this))); 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HandleWriteResult(result); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::OnWritten(int result) { 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(write_pending_); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(result, net::ERR_IO_PENDING); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_pending_ = false; 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HandleWriteResult(result); 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoWrite(); 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::HandleWriteResult(int result) { 396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(write_buffer_.get()); 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result >= 0) { 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_buffer_->DidConsume(result); 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (write_buffer_->BytesRemaining() == 0) { 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_sender_->Send(new P2PMsg_OnSendComplete(id_)); 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (write_queue_.empty()) { 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_buffer_ = NULL; 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_buffer_ = write_queue_.front(); 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_queue_.pop(); 406ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch // Update how many bytes are still waiting to be sent. 407ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch DecrementDelayedBytes(write_buffer_->size()); 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (result == net::ERR_IO_PENDING) { 411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_pending_ = true; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Error when sending data in TCP socket: " << result; 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnError(); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)P2PSocketHost* P2PSocketHostTcpBase::AcceptIncomingTcpConnection( 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::IPEndPoint& remote_address, int id) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnError(); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcpBase::DidCompleteRead(int result) { 426b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_EQ(state_, STATE_OPEN); 427b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 428b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (result == net::ERR_IO_PENDING) { 429b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 430b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else if (result < 0) { 431b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LOG(ERROR) << "Error when reading from TCP socket: " << result; 432b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) OnError(); 433b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 434b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) read_buffer_->set_offset(read_buffer_->offset() + result); 437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) char* head = read_buffer_->StartOfBuffer(); // Purely a convenience. 438b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int pos = 0; 439b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) while (pos <= read_buffer_->offset() && state_ == STATE_OPEN) { 440b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int consumed = ProcessInput(head + pos, read_buffer_->offset() - pos); 441b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!consumed) 442b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 443b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) pos += consumed; 444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We've consumed all complete packets from the buffer; now move any remaining 446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // bytes to the head of the buffer and set offset to reflect this. 447b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (pos && pos <= read_buffer_->offset()) { 448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) memmove(head, head + pos, read_buffer_->offset() - pos); 449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) read_buffer_->set_offset(read_buffer_->offset() - pos); 450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool P2PSocketHostTcpBase::SetOption(P2PSocketOption option, int value) { 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(STATE_OPEN, state_); 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (option) { 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case P2P_SOCKET_OPT_RCVBUF: 457c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return socket_->SetReceiveBufferSize(value) == net::OK; 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case P2P_SOCKET_OPT_SNDBUF: 459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return socket_->SetSendBufferSize(value) == net::OK; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case P2P_SOCKET_OPT_DSCP: 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; // For TCP sockets DSCP setting is not available. 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) default: 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 46846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)P2PSocketHostTcp::P2PSocketHostTcp(IPC::Sender* message_sender, 46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int socket_id, 47046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) P2PSocketType type, 47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::URLRequestContextGetter* url_context) 47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : P2PSocketHostTcpBase(message_sender, socket_id, type, url_context) { 473c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK(type == P2P_SOCKET_TCP_CLIENT || 474c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch type == P2P_SOCKET_SSLTCP_CLIENT || 475c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch type == P2P_SOCKET_TLS_CLIENT); 476b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 477b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 478b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)P2PSocketHostTcp::~P2PSocketHostTcp() { 479b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 480b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 481b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int P2PSocketHostTcp::ProcessInput(char* input, int input_len) { 482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (input_len < kPacketHeaderSize) 483b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return 0; 484b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int packet_size = base::NetToHost16(*reinterpret_cast<uint16*>(input)); 485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (input_len < packet_size + kPacketHeaderSize) 486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return 0; 487b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int consumed = kPacketHeaderSize; 489b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) char* cur = input + consumed; 490b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) std::vector<char> data(cur, cur + packet_size); 491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) OnPacket(data); 492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) consumed += packet_size; 493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return consumed; 494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to, 497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::vector<char>& data, 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const rtc::PacketOptions& options) { 499b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int size = kPacketHeaderSize + data.size(); 500b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<net::DrainableIOBuffer> buffer = 501b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) new net::DrainableIOBuffer(new net::IOBuffer(size), size); 502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *reinterpret_cast<uint16*>(buffer->data()) = base::HostToNet16(data.size()); 503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size()); 504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) packet_processing_helpers::ApplyPacketOptions( 506effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch buffer->data() + kPacketHeaderSize, 507effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch buffer->BytesRemaining() - kPacketHeaderSize, 508effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch options, 0); 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) WriteOrQueue(buffer); 511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// P2PSocketHostStunTcp 514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochP2PSocketHostStunTcp::P2PSocketHostStunTcp( 51546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) IPC::Sender* message_sender, 51646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int socket_id, 51746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) P2PSocketType type, 51846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) net::URLRequestContextGetter* url_context) 51946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : P2PSocketHostTcpBase(message_sender, socket_id, type, url_context) { 520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(type == P2P_SOCKET_STUN_TCP_CLIENT || 521c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch type == P2P_SOCKET_STUN_SSLTCP_CLIENT || 522c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch type == P2P_SOCKET_STUN_TLS_CLIENT); 523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)P2PSocketHostStunTcp::~P2PSocketHostStunTcp() { 526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int P2PSocketHostStunTcp::ProcessInput(char* input, int input_len) { 529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (input_len < kPacketHeaderSize + kPacketLengthOffset) 530b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return 0; 531b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 532b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int pad_bytes; 533b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int packet_size = GetExpectedPacketSize( 534b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) input, input_len, &pad_bytes); 535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 536b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (input_len < packet_size + pad_bytes) 537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return 0; 538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 539b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // We have a complete packet. Read through it. 540b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int consumed = 0; 541b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) char* cur = input; 542b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) std::vector<char> data(cur, cur + packet_size); 543b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) OnPacket(data); 544b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) consumed += packet_size; 545b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) consumed += pad_bytes; 546b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return consumed; 547b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 548b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 549b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void P2PSocketHostStunTcp::DoSend(const net::IPEndPoint& to, 550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::vector<char>& data, 5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const rtc::PacketOptions& options) { 552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Each packet is expected to have header (STUN/TURN ChannelData), where 553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // header contains message type and and length of message. 554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (data.size() < kPacketHeaderSize + kPacketLengthOffset) { 555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NOTREACHED(); 556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) OnError(); 557b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 558b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 559b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 560b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int pad_bytes; 561b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) size_t expected_len = GetExpectedPacketSize( 562b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) &data[0], data.size(), &pad_bytes); 563b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 564b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Accepts only complete STUN/TURN packets. 565b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (data.size() != expected_len) { 566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NOTREACHED(); 567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) OnError(); 568b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 569b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 570b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 571b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Add any pad bytes to the total size. 572b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int size = data.size() + pad_bytes; 573b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_refptr<net::DrainableIOBuffer> buffer = 575b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) new net::DrainableIOBuffer(new net::IOBuffer(size), size); 576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) memcpy(buffer->data(), &data[0], data.size()); 577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) packet_processing_helpers::ApplyPacketOptions( 579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffer->data(), data.size(), options, 0); 580a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (pad_bytes) { 582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) char padding[4] = {0}; 583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_LE(pad_bytes, 4); 584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) memcpy(buffer->data() + data.size(), padding, pad_bytes); 585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) WriteOrQueue(buffer); 58746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 58846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (dump_outgoing_rtp_packet_) 58946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DumpRtpPacket(buffer->data(), data.size(), false); 590b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 591b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 592b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int P2PSocketHostStunTcp::GetExpectedPacketSize( 593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const char* data, int len, int* pad_bytes) { 594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_LE(kTurnChannelDataHeaderSize, len); 595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Both stun and turn had length at offset 2. 596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int packet_size = base::NetToHost16(*reinterpret_cast<const uint16*>( 597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) data + kPacketLengthOffset)); 598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Get packet type (STUN or TURN). 600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) uint16 msg_type = base::NetToHost16(*reinterpret_cast<const uint16*>(data)); 601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *pad_bytes = 0; 603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Add heder length to packet length. 604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if ((msg_type & 0xC000) == 0) { 605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) packet_size += kStunHeaderSize; 606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) packet_size += kTurnChannelDataHeaderSize; 608b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Calculate any padding if present. 609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (packet_size % 4) 610b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *pad_bytes = 4 - packet_size % 4; 611b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 612b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return packet_size; 613b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 614b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 615b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} // namespace content 616