1 // Copyright 2013 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/pepper/pepper_tcp_socket_message_filter.h"
10 #include "base/logging.h"
11 #include "build/build_config.h"
12 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
13 #include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
14 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/resource_context.h"
19 #include "content/public/common/socket_permission_request.h"
20 #include "net/base/address_family.h"
21 #include "net/base/host_port_pair.h"
22 #include "net/base/io_buffer.h"
23 #include "net/base/net_errors.h"
24 #include "net/dns/single_request_host_resolver.h"
25 #include "net/socket/client_socket_factory.h"
26 #include "net/socket/client_socket_handle.h"
27 #include "net/socket/ssl_client_socket.h"
28 #include "net/socket/tcp_client_socket.h"
29 #include "ppapi/host/dispatch_host_message.h"
30 #include "ppapi/host/error_conversion.h"
31 #include "ppapi/host/ppapi_host.h"
32 #include "ppapi/host/resource_host.h"
33 #include "ppapi/proxy/ppapi_messages.h"
34 #include "ppapi/proxy/tcp_socket_resource_base.h"
35 #include "ppapi/shared_impl/private/net_address_private_impl.h"
37 using ppapi::NetAddressPrivateImpl;
38 using ppapi::host::NetErrorToPepperError;
39 using ppapi::proxy::TCPSocketResourceBase;
40 using ppapi::TCPSocketState;
41 using ppapi::TCPSocketVersion;
45 size_t g_num_instances = 0;
51 PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
52 ContentBrowserPepperHostFactory* factory,
53 BrowserPpapiHostImpl* host,
55 TCPSocketVersion version)
57 external_plugin_(host->external_plugin()),
58 render_process_id_(0),
60 ppapi_host_(host->GetPpapiHost()),
63 state_(TCPSocketState::INITIAL),
64 end_of_file_reached_(false),
65 bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
67 socket_(new net::TCPSocket(NULL, net::NetLog::Source())),
68 ssl_context_helper_(host->ssl_context_helper()),
69 pending_accept_(false) {
72 if (!host->GetRenderViewIDsForInstance(instance,
79 PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
80 BrowserPpapiHostImpl* host,
82 TCPSocketVersion version,
83 scoped_ptr<net::TCPSocket> socket)
85 external_plugin_(host->external_plugin()),
86 render_process_id_(0),
88 ppapi_host_(host->GetPpapiHost()),
91 state_(TCPSocketState::CONNECTED),
92 end_of_file_reached_(false),
93 bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
95 socket_(socket.Pass()),
96 ssl_context_helper_(host->ssl_context_helper()),
97 pending_accept_(false) {
99 DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
102 if (!host->GetRenderViewIDsForInstance(instance,
109 PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
113 ssl_socket_->Disconnect();
118 size_t PepperTCPSocketMessageFilter::GetNumInstances() {
119 return g_num_instances;
122 scoped_refptr<base::TaskRunner>
123 PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
124 const IPC::Message& message) {
125 switch (message.type()) {
126 case PpapiHostMsg_TCPSocket_Bind::ID:
127 case PpapiHostMsg_TCPSocket_Connect::ID:
128 case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
129 case PpapiHostMsg_TCPSocket_Listen::ID:
130 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
131 case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
132 case PpapiHostMsg_TCPSocket_Read::ID:
133 case PpapiHostMsg_TCPSocket_Write::ID:
134 case PpapiHostMsg_TCPSocket_Accept::ID:
135 case PpapiHostMsg_TCPSocket_Close::ID:
136 case PpapiHostMsg_TCPSocket_SetOption::ID:
137 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
142 int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
143 const IPC::Message& msg,
144 ppapi::host::HostMessageContext* context) {
145 IPC_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
146 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
147 PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
148 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
149 PpapiHostMsg_TCPSocket_Connect, OnMsgConnect)
150 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
151 PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
152 OnMsgConnectWithNetAddress)
153 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
154 PpapiHostMsg_TCPSocket_SSLHandshake, OnMsgSSLHandshake)
155 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
156 PpapiHostMsg_TCPSocket_Read, OnMsgRead)
157 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
158 PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
159 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
160 PpapiHostMsg_TCPSocket_Listen, OnMsgListen)
161 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
162 PpapiHostMsg_TCPSocket_Accept, OnMsgAccept)
163 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
164 PpapiHostMsg_TCPSocket_Close, OnMsgClose)
165 PPAPI_DISPATCH_HOST_RESOURCE_CALL(
166 PpapiHostMsg_TCPSocket_SetOption, OnMsgSetOption)
167 IPC_END_MESSAGE_MAP()
168 return PP_ERROR_FAILED;
171 int32_t PepperTCPSocketMessageFilter::OnMsgBind(
172 const ppapi::host::HostMessageContext* context,
173 const PP_NetAddress_Private& net_addr) {
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
176 // This is only supported by PPB_TCPSocket v1.1 or above.
177 if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
179 return PP_ERROR_NOACCESS;
182 if (!pepper_socket_utils::CanUseSocketAPIs(
183 external_plugin_, false /* private_api */, NULL, render_process_id_,
185 return PP_ERROR_NOACCESS;
188 bind_input_addr_ = net_addr;
190 BrowserThread::PostTask(
191 BrowserThread::IO, FROM_HERE,
192 base::Bind(&PepperTCPSocketMessageFilter::DoBind, this,
193 context->MakeReplyMessageContext(), net_addr));
194 return PP_OK_COMPLETIONPENDING;
197 int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
198 const ppapi::host::HostMessageContext* context,
199 const std::string& host,
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
203 // This is only supported by PPB_TCPSocket_Private.
204 if (!IsPrivateAPI()) {
206 return PP_ERROR_NOACCESS;
209 SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT,
212 if (!pepper_socket_utils::CanUseSocketAPIs(
213 external_plugin_, true /* private_api */, &request,
214 render_process_id_, render_view_id_)) {
215 return PP_ERROR_NOACCESS;
218 RenderProcessHost* render_process_host =
219 RenderProcessHost::FromID(render_process_id_);
220 if (!render_process_host)
221 return PP_ERROR_FAILED;
222 BrowserContext* browser_context = render_process_host->GetBrowserContext();
223 if (!browser_context || !browser_context->GetResourceContext())
224 return PP_ERROR_FAILED;
226 BrowserThread::PostTask(
227 BrowserThread::IO, FROM_HERE,
228 base::Bind(&PepperTCPSocketMessageFilter::DoConnect, this,
229 context->MakeReplyMessageContext(),
230 host, port, browser_context->GetResourceContext()));
231 return PP_OK_COMPLETIONPENDING;
234 int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
235 const ppapi::host::HostMessageContext* context,
236 const PP_NetAddress_Private& net_addr) {
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
239 content::SocketPermissionRequest request =
240 pepper_socket_utils::CreateSocketPermissionRequest(
241 content::SocketPermissionRequest::TCP_CONNECT, net_addr);
242 if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, IsPrivateAPI(),
243 &request, render_process_id_,
245 return PP_ERROR_NOACCESS;
248 BrowserThread::PostTask(
249 BrowserThread::IO, FROM_HERE,
250 base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress, this,
251 context->MakeReplyMessageContext(), net_addr));
252 return PP_OK_COMPLETIONPENDING;
255 int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
256 const ppapi::host::HostMessageContext* context,
257 const std::string& server_name,
258 uint16_t server_port,
259 const std::vector<std::vector<char> >& trusted_certs,
260 const std::vector<std::vector<char> >& untrusted_certs) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
263 // Allow to do SSL handshake only if currently the socket has been connected
264 // and there isn't pending read or write.
265 if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
266 read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
267 return PP_ERROR_FAILED;
270 // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
271 net::IPEndPoint peer_address;
272 if (socket_->GetPeerAddress(&peer_address) != net::OK)
273 return PP_ERROR_FAILED;
275 scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
276 handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
277 new net::TCPClientSocket(socket_.Pass(), peer_address)));
278 net::ClientSocketFactory* factory =
279 net::ClientSocketFactory::GetDefaultFactory();
280 net::HostPortPair host_port_pair(server_name, server_port);
281 net::SSLClientSocketContext ssl_context;
282 ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
283 ssl_context.transport_security_state =
284 ssl_context_helper_->GetTransportSecurityState();
285 ssl_socket_ = factory->CreateSSLClientSocket(
286 handle.Pass(), host_port_pair, ssl_context_helper_->ssl_config(),
289 LOG(WARNING) << "Failed to create an SSL client socket.";
290 state_.CompletePendingTransition(false);
291 return PP_ERROR_FAILED;
294 state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
296 const ppapi::host::ReplyMessageContext reply_context(
297 context->MakeReplyMessageContext());
298 int net_result = ssl_socket_->Connect(
299 base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
300 base::Unretained(this), reply_context));
301 if (net_result != net::ERR_IO_PENDING)
302 OnSSLHandshakeCompleted(reply_context, net_result);
303 return PP_OK_COMPLETIONPENDING;
306 int32_t PepperTCPSocketMessageFilter::OnMsgRead(
307 const ppapi::host::HostMessageContext* context,
308 int32_t bytes_to_read) {
309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
310 if (!state_.IsConnected() || end_of_file_reached_)
311 return PP_ERROR_FAILED;
312 if (read_buffer_.get())
313 return PP_ERROR_INPROGRESS;
314 if (bytes_to_read <= 0 ||
315 bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
316 return PP_ERROR_BADARGUMENT;
319 ppapi::host::ReplyMessageContext reply_context(
320 context->MakeReplyMessageContext());
321 read_buffer_ = new net::IOBuffer(bytes_to_read);
323 int net_result = net::ERR_FAILED;
325 DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
326 net_result = socket_->Read(
329 base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
330 base::Unretained(this), reply_context));
331 } else if (ssl_socket_) {
332 DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
333 net_result = ssl_socket_->Read(
336 base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
337 base::Unretained(this), reply_context));
339 if (net_result != net::ERR_IO_PENDING)
340 OnReadCompleted(reply_context, net_result);
341 return PP_OK_COMPLETIONPENDING;
344 int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
345 const ppapi::host::HostMessageContext* context,
346 const std::string& data) {
347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
349 if (!state_.IsConnected())
350 return PP_ERROR_FAILED;
351 if (write_buffer_base_.get() || write_buffer_.get())
352 return PP_ERROR_INPROGRESS;
354 size_t data_size = data.size();
355 if (data_size == 0 ||
356 data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
357 return PP_ERROR_BADARGUMENT;
360 write_buffer_base_ = new net::IOBuffer(data_size);
361 memcpy(write_buffer_base_->data(), data.data(), data_size);
363 new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
364 DoWrite(context->MakeReplyMessageContext());
365 return PP_OK_COMPLETIONPENDING;
368 int32_t PepperTCPSocketMessageFilter::OnMsgListen(
369 const ppapi::host::HostMessageContext* context,
371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
373 // This is only supported by PPB_TCPSocket v1.1 or above.
374 if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
376 return PP_ERROR_NOACCESS;
379 content::SocketPermissionRequest request =
380 pepper_socket_utils::CreateSocketPermissionRequest(
381 content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
382 if (!pepper_socket_utils::CanUseSocketAPIs(
383 external_plugin_, false /* private_api */, &request,
384 render_process_id_, render_view_id_)) {
385 return PP_ERROR_NOACCESS;
388 BrowserThread::PostTask(
389 BrowserThread::IO, FROM_HERE,
390 base::Bind(&PepperTCPSocketMessageFilter::DoListen, this,
391 context->MakeReplyMessageContext(), backlog));
392 return PP_OK_COMPLETIONPENDING;
395 int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
396 const ppapi::host::HostMessageContext* context) {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
400 return PP_ERROR_INPROGRESS;
401 if (state_.state() != TCPSocketState::LISTENING)
402 return PP_ERROR_FAILED;
404 pending_accept_ = true;
405 ppapi::host::ReplyMessageContext reply_context(
406 context->MakeReplyMessageContext());
407 int net_result = socket_->Accept(
410 base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
411 base::Unretained(this), reply_context));
412 if (net_result != net::ERR_IO_PENDING)
413 OnAcceptCompleted(reply_context, net_result);
414 return PP_OK_COMPLETIONPENDING;
417 int32_t PepperTCPSocketMessageFilter::OnMsgClose(
418 const ppapi::host::HostMessageContext* context) {
419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
420 if (state_.state() == TCPSocketState::CLOSED)
423 state_.DoTransition(TCPSocketState::CLOSE, true);
424 // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
427 } else if (ssl_socket_) {
428 ssl_socket_->Disconnect();
433 int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
434 const ppapi::host::HostMessageContext* context,
435 PP_TCPSocket_Option name,
436 const ppapi::SocketOptionData& value) {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
440 case PP_TCPSOCKET_OPTION_NO_DELAY: {
441 if (state_.state() != TCPSocketState::CONNECTED)
442 return PP_ERROR_FAILED;
444 bool boolean_value = false;
445 if (!value.GetBool(&boolean_value))
446 return PP_ERROR_BADARGUMENT;
447 return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
449 case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
450 case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
451 if (state_.state() != TCPSocketState::CONNECTED)
452 return PP_ERROR_FAILED;
454 int32_t integer_value = 0;
455 if (!value.GetInt32(&integer_value) || integer_value <= 0)
456 return PP_ERROR_BADARGUMENT;
459 if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
460 if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
461 return PP_ERROR_BADARGUMENT;
462 result = socket_->SetSendBufferSize(integer_value);
464 if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
465 return PP_ERROR_BADARGUMENT;
466 result = socket_->SetReceiveBufferSize(integer_value);
468 return result ? PP_OK : PP_ERROR_FAILED;
472 return PP_ERROR_BADARGUMENT;
477 void PepperTCPSocketMessageFilter::DoBind(
478 const ppapi::host::ReplyMessageContext& context,
479 const PP_NetAddress_Private& net_addr) {
480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
482 if (state_.IsPending(TCPSocketState::BIND)) {
483 SendBindError(context, PP_ERROR_INPROGRESS);
486 if (!state_.IsValidTransition(TCPSocketState::BIND)) {
487 SendBindError(context, PP_ERROR_FAILED);
491 int pp_result = PP_OK;
493 net::IPAddressNumber address;
495 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
497 pp_result = PP_ERROR_ADDRESS_INVALID;
500 net::IPEndPoint bind_addr(address, port);
502 DCHECK(!socket_->IsValid());
503 pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
504 if (pp_result != PP_OK)
507 pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
508 if (pp_result != PP_OK)
511 pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
512 if (pp_result != PP_OK)
515 net::IPEndPoint ip_end_point_local;
516 pp_result = NetErrorToPepperError(
517 socket_->GetLocalAddress(&ip_end_point_local));
518 if (pp_result != PP_OK)
521 PP_NetAddress_Private local_addr =
522 NetAddressPrivateImpl::kInvalidNetAddress;
523 if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
524 ip_end_point_local.address(),
525 ip_end_point_local.port(),
527 pp_result = PP_ERROR_ADDRESS_INVALID;
531 SendBindReply(context, PP_OK, local_addr);
532 state_.DoTransition(TCPSocketState::BIND, true);
535 if (socket_->IsValid())
537 SendBindError(context, pp_result);
538 state_.DoTransition(TCPSocketState::BIND, false);
541 void PepperTCPSocketMessageFilter::DoConnect(
542 const ppapi::host::ReplyMessageContext& context,
543 const std::string& host,
545 ResourceContext* resource_context) {
546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
548 if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
549 SendConnectError(context, PP_ERROR_FAILED);
553 state_.SetPendingTransition(TCPSocketState::CONNECT);
555 address_list_.clear();
556 net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
557 resolver_.reset(new net::SingleRequestHostResolver(
558 resource_context->GetHostResolver()));
559 int net_result = resolver_->Resolve(
561 net::DEFAULT_PRIORITY,
563 base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
564 base::Unretained(this), context),
566 if (net_result != net::ERR_IO_PENDING)
567 OnResolveCompleted(context, net_result);
570 void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
571 const ppapi::host::ReplyMessageContext& context,
572 const PP_NetAddress_Private& net_addr) {
573 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
575 if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
576 SendConnectError(context, PP_ERROR_FAILED);
580 state_.SetPendingTransition(TCPSocketState::CONNECT);
582 net::IPAddressNumber address;
584 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
586 state_.CompletePendingTransition(false);
587 SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
591 // Copy the single IPEndPoint to address_list_.
593 address_list_.clear();
594 address_list_.push_back(net::IPEndPoint(address, port));
595 StartConnect(context);
598 void PepperTCPSocketMessageFilter::DoWrite(
599 const ppapi::host::ReplyMessageContext& context) {
600 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
601 DCHECK(write_buffer_base_.get());
602 DCHECK(write_buffer_.get());
603 DCHECK_GT(write_buffer_->BytesRemaining(), 0);
604 DCHECK(state_.IsConnected());
606 int net_result = net::ERR_FAILED;
608 DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
609 net_result = socket_->Write(
611 write_buffer_->BytesRemaining(),
612 base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
613 base::Unretained(this), context));
614 } else if (ssl_socket_) {
615 DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
616 net_result = ssl_socket_->Write(
618 write_buffer_->BytesRemaining(),
619 base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
620 base::Unretained(this), context));
622 if (net_result != net::ERR_IO_PENDING)
623 OnWriteCompleted(context, net_result);
626 void PepperTCPSocketMessageFilter::DoListen(
627 const ppapi::host::ReplyMessageContext& context,
629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
631 if (state_.IsPending(TCPSocketState::LISTEN)) {
632 SendListenReply(context, PP_ERROR_INPROGRESS);
635 if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
636 SendListenReply(context, PP_ERROR_FAILED);
640 int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
641 SendListenReply(context, pp_result);
642 state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
645 void PepperTCPSocketMessageFilter::OnResolveCompleted(
646 const ppapi::host::ReplyMessageContext& context,
648 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
650 if (!state_.IsPending(TCPSocketState::CONNECT)) {
651 DCHECK(state_.state() == TCPSocketState::CLOSED);
652 SendConnectError(context, PP_ERROR_FAILED);
656 if (net_result != net::OK) {
657 SendConnectError(context, NetErrorToPepperError(net_result));
658 state_.CompletePendingTransition(false);
662 StartConnect(context);
665 void PepperTCPSocketMessageFilter::StartConnect(
666 const ppapi::host::ReplyMessageContext& context) {
667 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
668 DCHECK(state_.IsPending(TCPSocketState::CONNECT));
669 DCHECK_LT(address_index_, address_list_.size());
671 int net_result = net::OK;
672 if (!socket_->IsValid())
673 net_result = socket_->Open(address_list_[address_index_].GetFamily());
675 if (net_result == net::OK) {
676 net_result = socket_->Connect(
677 address_list_[address_index_],
678 base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
679 base::Unretained(this), context));
681 if (net_result != net::ERR_IO_PENDING)
682 OnConnectCompleted(context, net_result);
685 void PepperTCPSocketMessageFilter::OnConnectCompleted(
686 const ppapi::host::ReplyMessageContext& context,
688 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
690 if (!state_.IsPending(TCPSocketState::CONNECT)) {
691 DCHECK(state_.state() == TCPSocketState::CLOSED);
692 SendConnectError(context, PP_ERROR_FAILED);
696 int32_t pp_result = NetErrorToPepperError(net_result);
698 if (pp_result != PP_OK)
701 net::IPEndPoint ip_end_point_local;
702 net::IPEndPoint ip_end_point_remote;
703 pp_result = NetErrorToPepperError(
704 socket_->GetLocalAddress(&ip_end_point_local));
705 if (pp_result != PP_OK)
707 pp_result = NetErrorToPepperError(
708 socket_->GetPeerAddress(&ip_end_point_remote));
709 if (pp_result != PP_OK)
712 PP_NetAddress_Private local_addr =
713 NetAddressPrivateImpl::kInvalidNetAddress;
714 PP_NetAddress_Private remote_addr =
715 NetAddressPrivateImpl::kInvalidNetAddress;
716 if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
717 ip_end_point_local.address(),
718 ip_end_point_local.port(),
720 !NetAddressPrivateImpl::IPEndPointToNetAddress(
721 ip_end_point_remote.address(),
722 ip_end_point_remote.port(),
724 pp_result = PP_ERROR_ADDRESS_INVALID;
728 socket_->SetDefaultOptionsForClient();
729 SendConnectReply(context, PP_OK, local_addr, remote_addr);
730 state_.CompletePendingTransition(true);
734 if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
735 DCHECK_EQ(1u, address_list_.size());
737 SendConnectError(context, pp_result);
738 state_.CompletePendingTransition(false);
740 // We have to recreate |socket_| because it doesn't allow a second connect
741 // attempt. We won't lose any state such as bound address or set options,
742 // because in the private or v1.0 API, connect must be the first operation.
743 socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
745 if (address_index_ + 1 < address_list_.size()) {
746 DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
748 StartConnect(context);
750 SendConnectError(context, pp_result);
751 // In order to maintain backward compatibility, allow further attempts to
752 // connect the socket.
753 state_ = TCPSocketState(TCPSocketState::INITIAL);
758 void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
759 const ppapi::host::ReplyMessageContext& context,
761 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
763 if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
764 DCHECK(state_.state() == TCPSocketState::CLOSED);
765 SendSSLHandshakeReply(context, PP_ERROR_FAILED);
769 SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
770 state_.CompletePendingTransition(net_result == net::OK);
773 void PepperTCPSocketMessageFilter::OnReadCompleted(
774 const ppapi::host::ReplyMessageContext& context,
776 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
777 DCHECK(read_buffer_.get());
779 if (net_result > 0) {
780 SendReadReply(context,
782 std::string(read_buffer_->data(), net_result));
783 } else if (net_result == 0) {
784 end_of_file_reached_ = true;
785 SendReadReply(context, PP_OK, std::string());
787 SendReadError(context, NetErrorToPepperError(net_result));
792 void PepperTCPSocketMessageFilter::OnWriteCompleted(
793 const ppapi::host::ReplyMessageContext& context,
795 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
796 DCHECK(write_buffer_base_.get());
797 DCHECK(write_buffer_.get());
799 // Note: For partial writes of 0 bytes, don't continue writing to avoid a
800 // likely infinite loop.
801 if (net_result > 0) {
802 write_buffer_->DidConsume(net_result);
803 if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
810 SendWriteReply(context, write_buffer_->BytesConsumed());
812 SendWriteReply(context, NetErrorToPepperError(net_result));
814 write_buffer_ = NULL;
815 write_buffer_base_ = NULL;
818 void PepperTCPSocketMessageFilter::OnAcceptCompleted(
819 const ppapi::host::ReplyMessageContext& context,
821 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
822 DCHECK(pending_accept_);
824 pending_accept_ = false;
826 if (net_result != net::OK) {
827 SendAcceptError(context, NetErrorToPepperError(net_result));
831 DCHECK(accepted_socket_.get());
833 net::IPEndPoint ip_end_point_local;
834 PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
835 PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
838 NetErrorToPepperError(accepted_socket_->GetLocalAddress(
839 &ip_end_point_local));
840 if (pp_result != PP_OK) {
841 SendAcceptError(context, pp_result);
844 if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
845 ip_end_point_local.address(),
846 ip_end_point_local.port(),
848 !NetAddressPrivateImpl::IPEndPointToNetAddress(
849 accepted_address_.address(),
850 accepted_address_.port(),
852 SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
856 // |factory_| is guaranteed to be non-NULL here. Only those instances created
857 // in CONNECTED state have a NULL |factory_|, while getting here requires
859 scoped_ptr<ppapi::host::ResourceHost> host =
860 factory_->CreateAcceptedTCPSocket(
861 instance_, version_, accepted_socket_.Pass());
863 SendAcceptError(context, PP_ERROR_NOSPACE);
866 int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
868 SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
870 SendAcceptError(context, PP_ERROR_NOSPACE);
873 void PepperTCPSocketMessageFilter::SendBindReply(
874 const ppapi::host::ReplyMessageContext& context,
876 const PP_NetAddress_Private& local_addr) {
877 ppapi::host::ReplyMessageContext reply_context(context);
878 reply_context.params.set_result(pp_result);
879 SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
882 void PepperTCPSocketMessageFilter::SendBindError(
883 const ppapi::host::ReplyMessageContext& context,
885 SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
888 void PepperTCPSocketMessageFilter::SendConnectReply(
889 const ppapi::host::ReplyMessageContext& context,
891 const PP_NetAddress_Private& local_addr,
892 const PP_NetAddress_Private& remote_addr) {
893 ppapi::host::ReplyMessageContext reply_context(context);
894 reply_context.params.set_result(pp_result);
895 SendReply(reply_context,
896 PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
899 void PepperTCPSocketMessageFilter::SendConnectError(
900 const ppapi::host::ReplyMessageContext& context,
902 SendConnectReply(context,
904 NetAddressPrivateImpl::kInvalidNetAddress,
905 NetAddressPrivateImpl::kInvalidNetAddress);
908 void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
909 const ppapi::host::ReplyMessageContext& context,
911 ppapi::host::ReplyMessageContext reply_context(context);
912 reply_context.params.set_result(pp_result);
913 ppapi::PPB_X509Certificate_Fields certificate_fields;
914 if (pp_result == PP_OK) {
915 // Our socket is guaranteed to be an SSL socket if we get here.
916 net::SSLInfo ssl_info;
917 ssl_socket_->GetSSLInfo(&ssl_info);
918 if (ssl_info.cert.get()) {
919 pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
920 &certificate_fields);
923 SendReply(reply_context,
924 PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
927 void PepperTCPSocketMessageFilter::SendReadReply(
928 const ppapi::host::ReplyMessageContext& context,
930 const std::string& data) {
931 ppapi::host::ReplyMessageContext reply_context(context);
932 reply_context.params.set_result(pp_result);
933 SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
936 void PepperTCPSocketMessageFilter::SendReadError(
937 const ppapi::host::ReplyMessageContext& context,
939 SendReadReply(context, pp_error, std::string());
942 void PepperTCPSocketMessageFilter::SendWriteReply(
943 const ppapi::host::ReplyMessageContext& context,
945 ppapi::host::ReplyMessageContext reply_context(context);
946 reply_context.params.set_result(pp_result);
947 SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
950 void PepperTCPSocketMessageFilter::SendListenReply(
951 const ppapi::host::ReplyMessageContext& context,
953 ppapi::host::ReplyMessageContext reply_context(context);
954 reply_context.params.set_result(pp_result);
955 SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
958 void PepperTCPSocketMessageFilter::SendAcceptReply(
959 const ppapi::host::ReplyMessageContext& context,
962 const PP_NetAddress_Private& local_addr,
963 const PP_NetAddress_Private& remote_addr) {
964 ppapi::host::ReplyMessageContext reply_context(context);
965 reply_context.params.set_result(pp_result);
966 SendReply(reply_context,
967 PpapiPluginMsg_TCPSocket_AcceptReply(
968 pending_host_id, local_addr, remote_addr));
971 void PepperTCPSocketMessageFilter::SendAcceptError(
972 const ppapi::host::ReplyMessageContext& context,
974 SendAcceptReply(context, pp_error, 0,
975 NetAddressPrivateImpl::kInvalidNetAddress,
976 NetAddressPrivateImpl::kInvalidNetAddress);
979 } // namespace content