Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / renderer_host / p2p / socket_host_tcp.cc
blob220b3cce6bbec0e1319582307c5189b3cb27b6a5
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.
5 #include "content/browser/renderer_host/p2p/socket_host_tcp.h"
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"
23 namespace {
25 typedef uint16 PacketLength;
26 const int kPacketHeaderSize = sizeof(PacketLength);
27 const int kReadBufferSize = 4096;
28 const int kPacketLengthOffset = 2;
29 const int kTurnChannelDataHeaderSize = 4;
30 const int kRecvSocketBufferSize = 128 * 1024;
31 const int kSendSocketBufferSize = 128 * 1024;
33 bool IsTlsClientSocket(content::P2PSocketType type) {
34 return (type == content::P2P_SOCKET_STUN_TLS_CLIENT ||
35 type == content::P2P_SOCKET_TLS_CLIENT);
38 bool IsPseudoTlsClientSocket(content::P2PSocketType type) {
39 return (type == content::P2P_SOCKET_SSLTCP_CLIENT ||
40 type == content::P2P_SOCKET_STUN_SSLTCP_CLIENT);
43 } // namespace
45 namespace content {
47 P2PSocketHostTcpBase::P2PSocketHostTcpBase(
48 IPC::Sender* message_sender, int id,
49 P2PSocketType type, net::URLRequestContextGetter* url_context)
50 : P2PSocketHost(message_sender, id),
51 write_pending_(false),
52 connected_(false),
53 type_(type),
54 url_context_(url_context) {
57 P2PSocketHostTcpBase::~P2PSocketHostTcpBase() {
58 if (state_ == STATE_OPEN) {
59 DCHECK(socket_.get());
60 socket_.reset();
64 bool P2PSocketHostTcpBase::InitAccepted(const net::IPEndPoint& remote_address,
65 net::StreamSocket* socket) {
66 DCHECK(socket);
67 DCHECK_EQ(state_, STATE_UNINITIALIZED);
69 remote_address_.ip_address = remote_address;
70 // TODO(ronghuawu): Add FakeSSLServerSocket.
71 socket_.reset(socket);
72 state_ = STATE_OPEN;
73 DoRead();
74 return state_ != STATE_ERROR;
77 bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
78 const P2PHostAndIPEndPoint& remote_address) {
79 DCHECK_EQ(state_, STATE_UNINITIALIZED);
81 remote_address_ = remote_address;
82 state_ = STATE_CONNECTING;
84 net::HostPortPair dest_host_port_pair =
85 net::HostPortPair::FromIPEndPoint(remote_address.ip_address);
86 // TODO(mallinath) - We are ignoring local_address altogether. We should
87 // find a way to inject this into ProxyResolvingClientSocket. This could be
88 // a problem on multi-homed host.
90 // The default SSLConfig is good enough for us for now.
91 const net::SSLConfig ssl_config;
92 socket_.reset(new jingle_glue::ProxyResolvingClientSocket(
93 NULL, // Default socket pool provided by the net::Proxy.
94 url_context_,
95 ssl_config,
96 dest_host_port_pair));
98 int status = socket_->Connect(
99 base::Bind(&P2PSocketHostTcpBase::OnConnected,
100 base::Unretained(this)));
101 if (status != net::ERR_IO_PENDING) {
102 // We defer execution of ProcessConnectDone instead of calling it
103 // directly here as the caller may not expect an error/close to
104 // happen here. This is okay, as from the caller's point of view,
105 // the connect always happens asynchronously.
106 base::MessageLoop* message_loop = base::MessageLoop::current();
107 CHECK(message_loop);
108 message_loop->PostTask(
109 FROM_HERE,
110 base::Bind(&P2PSocketHostTcpBase::OnConnected,
111 base::Unretained(this), status));
114 return state_ != STATE_ERROR;
117 void P2PSocketHostTcpBase::OnError() {
118 socket_.reset();
120 if (state_ == STATE_UNINITIALIZED || state_ == STATE_CONNECTING ||
121 state_ == STATE_TLS_CONNECTING || state_ == STATE_OPEN) {
122 message_sender_->Send(new P2PMsg_OnError(id_));
125 state_ = STATE_ERROR;
128 void P2PSocketHostTcpBase::OnConnected(int result) {
129 DCHECK_EQ(state_, STATE_CONNECTING);
130 DCHECK_NE(result, net::ERR_IO_PENDING);
132 if (result != net::OK) {
133 OnError();
134 return;
137 if (IsTlsClientSocket(type_)) {
138 state_ = STATE_TLS_CONNECTING;
139 StartTls();
140 } else if (IsPseudoTlsClientSocket(type_)) {
141 scoped_ptr<net::StreamSocket> transport_socket = socket_.Pass();
142 socket_.reset(
143 new jingle_glue::FakeSSLClientSocket(transport_socket.Pass()));
144 state_ = STATE_TLS_CONNECTING;
145 int status = socket_->Connect(
146 base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
147 base::Unretained(this)));
148 if (status != net::ERR_IO_PENDING) {
149 ProcessTlsSslConnectDone(status);
151 } else {
152 // If we are not doing TLS, we are ready to send data now.
153 // In case of TLS, SignalConnect will be sent only after TLS handshake is
154 // successfull. So no buffering will be done at socket handlers if any
155 // packets sent before that by the application.
156 OnOpen();
160 void P2PSocketHostTcpBase::StartTls() {
161 DCHECK_EQ(state_, STATE_TLS_CONNECTING);
162 DCHECK(socket_.get());
164 scoped_ptr<net::ClientSocketHandle> socket_handle(
165 new net::ClientSocketHandle());
166 socket_handle->SetSocket(socket_.Pass());
168 net::SSLClientSocketContext context;
169 context.cert_verifier = url_context_->GetURLRequestContext()->cert_verifier();
170 context.transport_security_state =
171 url_context_->GetURLRequestContext()->transport_security_state();
172 DCHECK(context.transport_security_state);
174 // Default ssl config.
175 const net::SSLConfig ssl_config;
176 net::HostPortPair dest_host_port_pair =
177 net::HostPortPair::FromIPEndPoint(remote_address_.ip_address);
178 if (!remote_address_.hostname.empty())
179 dest_host_port_pair.set_host(remote_address_.hostname);
181 net::ClientSocketFactory* socket_factory =
182 net::ClientSocketFactory::GetDefaultFactory();
183 DCHECK(socket_factory);
185 socket_ = socket_factory->CreateSSLClientSocket(
186 socket_handle.Pass(), dest_host_port_pair, ssl_config, context);
187 int status = socket_->Connect(
188 base::Bind(&P2PSocketHostTcpBase::ProcessTlsSslConnectDone,
189 base::Unretained(this)));
190 if (status != net::ERR_IO_PENDING) {
191 ProcessTlsSslConnectDone(status);
195 void P2PSocketHostTcpBase::ProcessTlsSslConnectDone(int status) {
196 DCHECK_NE(status, net::ERR_IO_PENDING);
197 DCHECK_EQ(state_, STATE_TLS_CONNECTING);
198 if (status != net::OK) {
199 OnError();
200 return;
202 OnOpen();
205 void P2PSocketHostTcpBase::OnOpen() {
206 state_ = STATE_OPEN;
207 // Setting socket send and receive buffer size.
208 if (net::OK != socket_->SetReceiveBufferSize(kRecvSocketBufferSize)) {
209 LOG(WARNING) << "Failed to set socket receive buffer size to "
210 << kRecvSocketBufferSize;
213 if (net::OK != socket_->SetSendBufferSize(kSendSocketBufferSize)) {
214 LOG(WARNING) << "Failed to set socket send buffer size to "
215 << kSendSocketBufferSize;
218 DoSendSocketCreateMsg();
219 DoRead();
222 void P2PSocketHostTcpBase::DoSendSocketCreateMsg() {
223 DCHECK(socket_.get());
225 net::IPEndPoint address;
226 int result = socket_->GetLocalAddress(&address);
227 if (result < 0) {
228 LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get local"
229 << " address: " << result;
230 OnError();
231 return;
234 VLOG(1) << "Local address: " << address.ToString();
236 // If we are not doing TLS, we are ready to send data now.
237 // In case of TLS SignalConnect will be sent only after TLS handshake is
238 // successfull. So no buffering will be done at socket handlers if any
239 // packets sent before that by the application.
240 message_sender_->Send(new P2PMsg_OnSocketCreated(id_, address));
243 void P2PSocketHostTcpBase::DoRead() {
244 int result;
245 do {
246 if (!read_buffer_.get()) {
247 read_buffer_ = new net::GrowableIOBuffer();
248 read_buffer_->SetCapacity(kReadBufferSize);
249 } else if (read_buffer_->RemainingCapacity() < kReadBufferSize) {
250 // Make sure that we always have at least kReadBufferSize of
251 // remaining capacity in the read buffer. Normally all packets
252 // are smaller than kReadBufferSize, so this is not really
253 // required.
254 read_buffer_->SetCapacity(read_buffer_->capacity() + kReadBufferSize -
255 read_buffer_->RemainingCapacity());
257 result = socket_->Read(
258 read_buffer_.get(),
259 read_buffer_->RemainingCapacity(),
260 base::Bind(&P2PSocketHostTcp::OnRead, base::Unretained(this)));
261 DidCompleteRead(result);
262 } while (result > 0);
265 void P2PSocketHostTcpBase::OnRead(int result) {
266 DidCompleteRead(result);
267 if (state_ == STATE_OPEN) {
268 DoRead();
272 void P2PSocketHostTcpBase::OnPacket(const std::vector<char>& data) {
273 if (!connected_) {
274 P2PSocketHost::StunMessageType type;
275 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
276 if (stun && IsRequestOrResponse(type)) {
277 connected_ = true;
278 } else if (!stun || type == STUN_DATA_INDICATION) {
279 LOG(ERROR) << "Received unexpected data packet from "
280 << remote_address_.ip_address.ToString()
281 << " before STUN binding is finished. "
282 << "Terminating connection.";
283 OnError();
284 return;
288 message_sender_->Send(new P2PMsg_OnDataReceived(
289 id_, remote_address_.ip_address, data, base::TimeTicks::Now()));
292 // Note: dscp is not actually used on TCP sockets as this point,
293 // but may be honored in the future.
294 void P2PSocketHostTcpBase::Send(const net::IPEndPoint& to,
295 const std::vector<char>& data,
296 const talk_base::PacketOptions& options,
297 uint64 packet_id) {
298 if (!socket_) {
299 // The Send message may be sent after the an OnError message was
300 // sent by hasn't been processed the renderer.
301 return;
304 if (!(to == remote_address_.ip_address)) {
305 // Renderer should use this socket only to send data to |remote_address_|.
306 NOTREACHED();
307 OnError();
308 return;
311 if (!connected_) {
312 P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
313 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
314 if (!stun || type == STUN_DATA_INDICATION) {
315 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString()
316 << " before STUN binding is finished.";
317 OnError();
318 return;
322 DoSend(to, data, options);
325 void P2PSocketHostTcpBase::WriteOrQueue(
326 scoped_refptr<net::DrainableIOBuffer>& buffer) {
327 if (write_buffer_.get()) {
328 write_queue_.push(buffer);
329 return;
332 write_buffer_ = buffer;
333 DoWrite();
336 void P2PSocketHostTcpBase::DoWrite() {
337 while (write_buffer_.get() && state_ == STATE_OPEN && !write_pending_) {
338 int result = socket_->Write(
339 write_buffer_.get(),
340 write_buffer_->BytesRemaining(),
341 base::Bind(&P2PSocketHostTcp::OnWritten, base::Unretained(this)));
342 HandleWriteResult(result);
346 void P2PSocketHostTcpBase::OnWritten(int result) {
347 DCHECK(write_pending_);
348 DCHECK_NE(result, net::ERR_IO_PENDING);
350 write_pending_ = false;
351 HandleWriteResult(result);
352 DoWrite();
355 void P2PSocketHostTcpBase::HandleWriteResult(int result) {
356 DCHECK(write_buffer_.get());
357 if (result >= 0) {
358 write_buffer_->DidConsume(result);
359 if (write_buffer_->BytesRemaining() == 0) {
360 message_sender_->Send(new P2PMsg_OnSendComplete(id_));
361 if (write_queue_.empty()) {
362 write_buffer_ = NULL;
363 } else {
364 write_buffer_ = write_queue_.front();
365 write_queue_.pop();
368 } else if (result == net::ERR_IO_PENDING) {
369 write_pending_ = true;
370 } else {
371 LOG(ERROR) << "Error when sending data in TCP socket: " << result;
372 OnError();
376 P2PSocketHost* P2PSocketHostTcpBase::AcceptIncomingTcpConnection(
377 const net::IPEndPoint& remote_address, int id) {
378 NOTREACHED();
379 OnError();
380 return NULL;
383 void P2PSocketHostTcpBase::DidCompleteRead(int result) {
384 DCHECK_EQ(state_, STATE_OPEN);
386 if (result == net::ERR_IO_PENDING) {
387 return;
388 } else if (result < 0) {
389 LOG(ERROR) << "Error when reading from TCP socket: " << result;
390 OnError();
391 return;
394 read_buffer_->set_offset(read_buffer_->offset() + result);
395 char* head = read_buffer_->StartOfBuffer(); // Purely a convenience.
396 int pos = 0;
397 while (pos <= read_buffer_->offset() && state_ == STATE_OPEN) {
398 int consumed = ProcessInput(head + pos, read_buffer_->offset() - pos);
399 if (!consumed)
400 break;
401 pos += consumed;
403 // We've consumed all complete packets from the buffer; now move any remaining
404 // bytes to the head of the buffer and set offset to reflect this.
405 if (pos && pos <= read_buffer_->offset()) {
406 memmove(head, head + pos, read_buffer_->offset() - pos);
407 read_buffer_->set_offset(read_buffer_->offset() - pos);
411 bool P2PSocketHostTcpBase::SetOption(P2PSocketOption option, int value) {
412 DCHECK_EQ(STATE_OPEN, state_);
413 switch (option) {
414 case P2P_SOCKET_OPT_RCVBUF:
415 return socket_->SetReceiveBufferSize(value) == net::OK;
416 case P2P_SOCKET_OPT_SNDBUF:
417 return socket_->SetSendBufferSize(value) == net::OK;
418 case P2P_SOCKET_OPT_DSCP:
419 return false; // For TCP sockets DSCP setting is not available.
420 default:
421 NOTREACHED();
422 return false;
426 P2PSocketHostTcp::P2PSocketHostTcp(
427 IPC::Sender* message_sender, int id,
428 P2PSocketType type, net::URLRequestContextGetter* url_context)
429 : P2PSocketHostTcpBase(message_sender, id, type, url_context) {
430 DCHECK(type == P2P_SOCKET_TCP_CLIENT ||
431 type == P2P_SOCKET_SSLTCP_CLIENT ||
432 type == P2P_SOCKET_TLS_CLIENT);
435 P2PSocketHostTcp::~P2PSocketHostTcp() {
438 int P2PSocketHostTcp::ProcessInput(char* input, int input_len) {
439 if (input_len < kPacketHeaderSize)
440 return 0;
441 int packet_size = base::NetToHost16(*reinterpret_cast<uint16*>(input));
442 if (input_len < packet_size + kPacketHeaderSize)
443 return 0;
445 int consumed = kPacketHeaderSize;
446 char* cur = input + consumed;
447 std::vector<char> data(cur, cur + packet_size);
448 OnPacket(data);
449 consumed += packet_size;
450 return consumed;
453 void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to,
454 const std::vector<char>& data,
455 const talk_base::PacketOptions& options) {
456 int size = kPacketHeaderSize + data.size();
457 scoped_refptr<net::DrainableIOBuffer> buffer =
458 new net::DrainableIOBuffer(new net::IOBuffer(size), size);
459 *reinterpret_cast<uint16*>(buffer->data()) = base::HostToNet16(data.size());
460 memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size());
462 packet_processing_helpers::ApplyPacketOptions(
463 buffer->data() + kPacketHeaderSize,
464 buffer->BytesRemaining() - kPacketHeaderSize,
465 options, 0);
467 WriteOrQueue(buffer);
470 // P2PSocketHostStunTcp
471 P2PSocketHostStunTcp::P2PSocketHostStunTcp(
472 IPC::Sender* message_sender, int id,
473 P2PSocketType type, net::URLRequestContextGetter* url_context)
474 : P2PSocketHostTcpBase(message_sender, id, type, url_context) {
475 DCHECK(type == P2P_SOCKET_STUN_TCP_CLIENT ||
476 type == P2P_SOCKET_STUN_SSLTCP_CLIENT ||
477 type == P2P_SOCKET_STUN_TLS_CLIENT);
480 P2PSocketHostStunTcp::~P2PSocketHostStunTcp() {
483 int P2PSocketHostStunTcp::ProcessInput(char* input, int input_len) {
484 if (input_len < kPacketHeaderSize + kPacketLengthOffset)
485 return 0;
487 int pad_bytes;
488 int packet_size = GetExpectedPacketSize(
489 input, input_len, &pad_bytes);
491 if (input_len < packet_size + pad_bytes)
492 return 0;
494 // We have a complete packet. Read through it.
495 int consumed = 0;
496 char* cur = input;
497 std::vector<char> data(cur, cur + packet_size);
498 OnPacket(data);
499 consumed += packet_size;
500 consumed += pad_bytes;
501 return consumed;
504 void P2PSocketHostStunTcp::DoSend(const net::IPEndPoint& to,
505 const std::vector<char>& data,
506 const talk_base::PacketOptions& options) {
507 // Each packet is expected to have header (STUN/TURN ChannelData), where
508 // header contains message type and and length of message.
509 if (data.size() < kPacketHeaderSize + kPacketLengthOffset) {
510 NOTREACHED();
511 OnError();
512 return;
515 int pad_bytes;
516 size_t expected_len = GetExpectedPacketSize(
517 &data[0], data.size(), &pad_bytes);
519 // Accepts only complete STUN/TURN packets.
520 if (data.size() != expected_len) {
521 NOTREACHED();
522 OnError();
523 return;
526 // Add any pad bytes to the total size.
527 int size = data.size() + pad_bytes;
529 scoped_refptr<net::DrainableIOBuffer> buffer =
530 new net::DrainableIOBuffer(new net::IOBuffer(size), size);
531 memcpy(buffer->data(), &data[0], data.size());
533 packet_processing_helpers::ApplyPacketOptions(
534 buffer->data(), data.size(), options, 0);
536 if (pad_bytes) {
537 char padding[4] = {0};
538 DCHECK_LE(pad_bytes, 4);
539 memcpy(buffer->data() + data.size(), padding, pad_bytes);
541 WriteOrQueue(buffer);
544 int P2PSocketHostStunTcp::GetExpectedPacketSize(
545 const char* data, int len, int* pad_bytes) {
546 DCHECK_LE(kTurnChannelDataHeaderSize, len);
547 // Both stun and turn had length at offset 2.
548 int packet_size = base::NetToHost16(*reinterpret_cast<const uint16*>(
549 data + kPacketLengthOffset));
551 // Get packet type (STUN or TURN).
552 uint16 msg_type = base::NetToHost16(*reinterpret_cast<const uint16*>(data));
554 *pad_bytes = 0;
555 // Add heder length to packet length.
556 if ((msg_type & 0xC000) == 0) {
557 packet_size += kStunHeaderSize;
558 } else {
559 packet_size += kTurnChannelDataHeaderSize;
560 // Calculate any padding if present.
561 if (packet_size % 4)
562 *pad_bytes = 4 - packet_size % 4;
564 return packet_size;
567 } // namespace content