- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / pepper / pepper_tcp_socket_message_filter.cc
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.
4
5 #include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
6
7 #include <cstring>
8
9 #include "base/bind.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"
36
37 using ppapi::NetAddressPrivateImpl;
38 using ppapi::host::NetErrorToPepperError;
39 using ppapi::proxy::TCPSocketResourceBase;
40 using ppapi::TCPSocketState;
41 using ppapi::TCPSocketVersion;
42
43 namespace {
44
45 size_t g_num_instances = 0;
46
47 }  // namespace
48
49 namespace content {
50
51 PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
52     ContentBrowserPepperHostFactory* factory,
53     BrowserPpapiHostImpl* host,
54     PP_Instance instance,
55     TCPSocketVersion version)
56     : version_(version),
57       external_plugin_(host->external_plugin()),
58       render_process_id_(0),
59       render_view_id_(0),
60       ppapi_host_(host->GetPpapiHost()),
61       factory_(factory),
62       instance_(instance),
63       state_(TCPSocketState::INITIAL),
64       end_of_file_reached_(false),
65       bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
66       address_index_(0),
67       socket_(new net::TCPSocket(NULL, net::NetLog::Source())),
68       ssl_context_helper_(host->ssl_context_helper()),
69       pending_accept_(false) {
70   DCHECK(host);
71   ++g_num_instances;
72   if (!host->GetRenderViewIDsForInstance(instance,
73                                          &render_process_id_,
74                                          &render_view_id_)) {
75     NOTREACHED();
76   }
77 }
78
79 PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
80     BrowserPpapiHostImpl* host,
81     PP_Instance instance,
82     TCPSocketVersion version,
83     scoped_ptr<net::TCPSocket> socket)
84     : version_(version),
85       external_plugin_(host->external_plugin()),
86       render_process_id_(0),
87       render_view_id_(0),
88       ppapi_host_(host->GetPpapiHost()),
89       factory_(NULL),
90       instance_(instance),
91       state_(TCPSocketState::CONNECTED),
92       end_of_file_reached_(false),
93       bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
94       address_index_(0),
95       socket_(socket.Pass()),
96       ssl_context_helper_(host->ssl_context_helper()),
97       pending_accept_(false) {
98   DCHECK(host);
99   DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
100
101   ++g_num_instances;
102   if (!host->GetRenderViewIDsForInstance(instance,
103                                          &render_process_id_,
104                                          &render_view_id_)) {
105     NOTREACHED();
106   }
107 }
108
109 PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
110   if (socket_)
111     socket_->Close();
112   if (ssl_socket_)
113     ssl_socket_->Disconnect();
114   --g_num_instances;
115 }
116
117 // static
118 size_t PepperTCPSocketMessageFilter::GetNumInstances() {
119   return g_num_instances;
120 }
121
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);
138   }
139   return NULL;
140 }
141
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;
169 }
170
171 int32_t PepperTCPSocketMessageFilter::OnMsgBind(
172     const ppapi::host::HostMessageContext* context,
173     const PP_NetAddress_Private& net_addr) {
174   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
175
176   // This is only supported by PPB_TCPSocket v1.1 or above.
177   if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
178     NOTREACHED();
179     return PP_ERROR_NOACCESS;
180   }
181
182   if (!pepper_socket_utils::CanUseSocketAPIs(
183           external_plugin_, false /* private_api */, NULL, render_process_id_,
184           render_view_id_)) {
185     return PP_ERROR_NOACCESS;
186   }
187
188   bind_input_addr_ = net_addr;
189
190   BrowserThread::PostTask(
191       BrowserThread::IO, FROM_HERE,
192       base::Bind(&PepperTCPSocketMessageFilter::DoBind, this,
193                  context->MakeReplyMessageContext(), net_addr));
194   return PP_OK_COMPLETIONPENDING;
195 }
196
197 int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
198     const ppapi::host::HostMessageContext* context,
199     const std::string& host,
200     uint16_t port) {
201   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202
203   // This is only supported by PPB_TCPSocket_Private.
204   if (!IsPrivateAPI()) {
205     NOTREACHED();
206     return PP_ERROR_NOACCESS;
207   }
208
209   SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT,
210                                   host,
211                                   port);
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;
216   }
217
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;
225
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;
232 }
233
234 int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
235     const ppapi::host::HostMessageContext* context,
236     const PP_NetAddress_Private& net_addr) {
237   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
238
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_,
244                                              render_view_id_)) {
245     return PP_ERROR_NOACCESS;
246   }
247
248   BrowserThread::PostTask(
249       BrowserThread::IO, FROM_HERE,
250       base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress, this,
251                  context->MakeReplyMessageContext(), net_addr));
252   return PP_OK_COMPLETIONPENDING;
253 }
254
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));
262
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;
268   }
269
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;
274
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(),
287       ssl_context);
288   if (!ssl_socket_) {
289     LOG(WARNING) << "Failed to create an SSL client socket.";
290     state_.CompletePendingTransition(false);
291     return PP_ERROR_FAILED;
292   }
293
294   state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
295
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;
304 }
305
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;
317   }
318
319   ppapi::host::ReplyMessageContext reply_context(
320       context->MakeReplyMessageContext());
321   read_buffer_ = new net::IOBuffer(bytes_to_read);
322
323   int net_result = net::ERR_FAILED;
324   if (socket_) {
325     DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
326     net_result = socket_->Read(
327         read_buffer_.get(),
328         bytes_to_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(
334         read_buffer_.get(),
335         bytes_to_read,
336         base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
337                    base::Unretained(this), reply_context));
338   }
339   if (net_result != net::ERR_IO_PENDING)
340     OnReadCompleted(reply_context, net_result);
341   return PP_OK_COMPLETIONPENDING;
342 }
343
344 int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
345     const ppapi::host::HostMessageContext* context,
346     const std::string& data) {
347   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
348
349   if (!state_.IsConnected())
350     return PP_ERROR_FAILED;
351   if (write_buffer_base_.get() || write_buffer_.get())
352     return PP_ERROR_INPROGRESS;
353
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;
358   }
359
360   write_buffer_base_ = new net::IOBuffer(data_size);
361   memcpy(write_buffer_base_->data(), data.data(), data_size);
362   write_buffer_ =
363       new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
364   DoWrite(context->MakeReplyMessageContext());
365   return PP_OK_COMPLETIONPENDING;
366 }
367
368 int32_t PepperTCPSocketMessageFilter::OnMsgListen(
369     const ppapi::host::HostMessageContext* context,
370     int32_t backlog) {
371   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
372
373   // This is only supported by PPB_TCPSocket v1.1 or above.
374   if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
375     NOTREACHED();
376     return PP_ERROR_NOACCESS;
377   }
378
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;
386   }
387
388   BrowserThread::PostTask(
389       BrowserThread::IO, FROM_HERE,
390       base::Bind(&PepperTCPSocketMessageFilter::DoListen, this,
391                  context->MakeReplyMessageContext(), backlog));
392   return PP_OK_COMPLETIONPENDING;
393 }
394
395 int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
396     const ppapi::host::HostMessageContext* context) {
397   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
398
399   if (pending_accept_)
400     return PP_ERROR_INPROGRESS;
401   if (state_.state() != TCPSocketState::LISTENING)
402     return PP_ERROR_FAILED;
403
404   pending_accept_ = true;
405   ppapi::host::ReplyMessageContext reply_context(
406       context->MakeReplyMessageContext());
407   int net_result = socket_->Accept(
408       &accepted_socket_,
409       &accepted_address_,
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;
415 }
416
417 int32_t PepperTCPSocketMessageFilter::OnMsgClose(
418     const ppapi::host::HostMessageContext* context) {
419   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
420   if (state_.state() == TCPSocketState::CLOSED)
421     return PP_OK;
422
423   state_.DoTransition(TCPSocketState::CLOSE, true);
424   // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
425   if (socket_) {
426     socket_->Close();
427   } else if (ssl_socket_) {
428     ssl_socket_->Disconnect();
429   }
430   return PP_OK;
431 }
432
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));
438
439   switch (name) {
440     case PP_TCPSOCKET_OPTION_NO_DELAY: {
441       if (state_.state() != TCPSocketState::CONNECTED)
442         return PP_ERROR_FAILED;
443
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;
448     }
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;
453
454       int32_t integer_value = 0;
455       if (!value.GetInt32(&integer_value) || integer_value <= 0)
456         return PP_ERROR_BADARGUMENT;
457
458       bool result = false;
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);
463       } else {
464         if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
465           return PP_ERROR_BADARGUMENT;
466         result = socket_->SetReceiveBufferSize(integer_value);
467       }
468       return result ? PP_OK : PP_ERROR_FAILED;
469     }
470     default: {
471       NOTREACHED();
472       return PP_ERROR_BADARGUMENT;
473     }
474   }
475 }
476
477 void PepperTCPSocketMessageFilter::DoBind(
478     const ppapi::host::ReplyMessageContext& context,
479     const PP_NetAddress_Private& net_addr) {
480   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
481
482   if (state_.IsPending(TCPSocketState::BIND)) {
483     SendBindError(context, PP_ERROR_INPROGRESS);
484     return;
485   }
486   if (!state_.IsValidTransition(TCPSocketState::BIND)) {
487     SendBindError(context, PP_ERROR_FAILED);
488     return;
489   }
490
491   int pp_result = PP_OK;
492   do {
493     net::IPAddressNumber address;
494     int port;
495     if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
496                                                        &port)) {
497       pp_result = PP_ERROR_ADDRESS_INVALID;
498       break;
499     }
500     net::IPEndPoint bind_addr(address, port);
501
502     DCHECK(!socket_->IsValid());
503     pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
504     if (pp_result != PP_OK)
505       break;
506
507     pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
508     if (pp_result != PP_OK)
509       break;
510
511     pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
512     if (pp_result != PP_OK)
513       break;
514
515     net::IPEndPoint ip_end_point_local;
516     pp_result = NetErrorToPepperError(
517         socket_->GetLocalAddress(&ip_end_point_local));
518     if (pp_result != PP_OK)
519       break;
520
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(),
526             &local_addr)) {
527       pp_result = PP_ERROR_ADDRESS_INVALID;
528       break;
529     }
530
531     SendBindReply(context, PP_OK, local_addr);
532     state_.DoTransition(TCPSocketState::BIND, true);
533     return;
534   } while (false);
535   if (socket_->IsValid())
536     socket_->Close();
537   SendBindError(context, pp_result);
538   state_.DoTransition(TCPSocketState::BIND, false);
539 }
540
541 void PepperTCPSocketMessageFilter::DoConnect(
542     const ppapi::host::ReplyMessageContext& context,
543     const std::string& host,
544     uint16_t port,
545     ResourceContext* resource_context) {
546   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
547
548   if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
549     SendConnectError(context, PP_ERROR_FAILED);
550     return;
551   }
552
553   state_.SetPendingTransition(TCPSocketState::CONNECT);
554   address_index_ = 0;
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(
560       request_info,
561       net::DEFAULT_PRIORITY,
562       &address_list_,
563       base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
564                  base::Unretained(this), context),
565       net::BoundNetLog());
566   if (net_result != net::ERR_IO_PENDING)
567     OnResolveCompleted(context, net_result);
568 }
569
570 void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
571     const ppapi::host::ReplyMessageContext& context,
572     const PP_NetAddress_Private& net_addr) {
573   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
574
575   if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
576     SendConnectError(context, PP_ERROR_FAILED);
577     return;
578   }
579
580   state_.SetPendingTransition(TCPSocketState::CONNECT);
581
582   net::IPAddressNumber address;
583   int port;
584   if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
585                                                      &port)) {
586     state_.CompletePendingTransition(false);
587     SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
588     return;
589   }
590
591   // Copy the single IPEndPoint to address_list_.
592   address_index_ = 0;
593   address_list_.clear();
594   address_list_.push_back(net::IPEndPoint(address, port));
595   StartConnect(context);
596 }
597
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());
605
606   int net_result = net::ERR_FAILED;
607   if (socket_) {
608     DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
609     net_result = socket_->Write(
610         write_buffer_.get(),
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(
617         write_buffer_.get(),
618         write_buffer_->BytesRemaining(),
619         base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
620                    base::Unretained(this), context));
621   }
622   if (net_result != net::ERR_IO_PENDING)
623     OnWriteCompleted(context, net_result);
624 }
625
626 void PepperTCPSocketMessageFilter::DoListen(
627     const ppapi::host::ReplyMessageContext& context,
628     int32_t backlog) {
629   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
630
631   if (state_.IsPending(TCPSocketState::LISTEN)) {
632     SendListenReply(context, PP_ERROR_INPROGRESS);
633     return;
634   }
635   if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
636     SendListenReply(context, PP_ERROR_FAILED);
637     return;
638   }
639
640   int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
641   SendListenReply(context, pp_result);
642   state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
643 }
644
645 void PepperTCPSocketMessageFilter::OnResolveCompleted(
646     const ppapi::host::ReplyMessageContext& context,
647     int net_result) {
648   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
649
650   if (!state_.IsPending(TCPSocketState::CONNECT)) {
651     DCHECK(state_.state() == TCPSocketState::CLOSED);
652     SendConnectError(context, PP_ERROR_FAILED);
653     return;
654   }
655
656   if (net_result != net::OK) {
657     SendConnectError(context, NetErrorToPepperError(net_result));
658     state_.CompletePendingTransition(false);
659     return;
660   }
661
662   StartConnect(context);
663 }
664
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());
670
671   int net_result = net::OK;
672   if (!socket_->IsValid())
673     net_result = socket_->Open(address_list_[address_index_].GetFamily());
674
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));
680   }
681   if (net_result != net::ERR_IO_PENDING)
682     OnConnectCompleted(context, net_result);
683 }
684
685 void PepperTCPSocketMessageFilter::OnConnectCompleted(
686     const ppapi::host::ReplyMessageContext& context,
687     int net_result) {
688   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
689
690   if (!state_.IsPending(TCPSocketState::CONNECT)) {
691     DCHECK(state_.state() == TCPSocketState::CLOSED);
692     SendConnectError(context, PP_ERROR_FAILED);
693     return;
694   }
695
696   int32_t pp_result = NetErrorToPepperError(net_result);
697   do {
698     if (pp_result != PP_OK)
699       break;
700
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)
706       break;
707     pp_result = NetErrorToPepperError(
708         socket_->GetPeerAddress(&ip_end_point_remote));
709     if (pp_result != PP_OK)
710       break;
711
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(),
719             &local_addr) ||
720         !NetAddressPrivateImpl::IPEndPointToNetAddress(
721             ip_end_point_remote.address(),
722             ip_end_point_remote.port(),
723             &remote_addr)) {
724       pp_result = PP_ERROR_ADDRESS_INVALID;
725       break;
726     }
727
728     socket_->SetDefaultOptionsForClient();
729     SendConnectReply(context, PP_OK, local_addr, remote_addr);
730     state_.CompletePendingTransition(true);
731     return;
732   } while (false);
733
734   if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
735     DCHECK_EQ(1u, address_list_.size());
736
737     SendConnectError(context, pp_result);
738     state_.CompletePendingTransition(false);
739   } else {
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()));
744
745     if (address_index_ + 1 < address_list_.size()) {
746       DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
747       address_index_++;
748       StartConnect(context);
749     } else {
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);
754     }
755   }
756 }
757
758 void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
759     const ppapi::host::ReplyMessageContext& context,
760     int net_result) {
761   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
762
763   if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
764     DCHECK(state_.state() == TCPSocketState::CLOSED);
765     SendSSLHandshakeReply(context, PP_ERROR_FAILED);
766     return;
767   }
768
769   SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
770   state_.CompletePendingTransition(net_result == net::OK);
771 }
772
773 void PepperTCPSocketMessageFilter::OnReadCompleted(
774     const ppapi::host::ReplyMessageContext& context,
775     int net_result) {
776   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
777   DCHECK(read_buffer_.get());
778
779   if (net_result > 0) {
780     SendReadReply(context,
781                   PP_OK,
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());
786   } else {
787     SendReadError(context, NetErrorToPepperError(net_result));
788   }
789   read_buffer_ = NULL;
790 }
791
792 void PepperTCPSocketMessageFilter::OnWriteCompleted(
793     const ppapi::host::ReplyMessageContext& context,
794     int net_result) {
795   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
796   DCHECK(write_buffer_base_.get());
797   DCHECK(write_buffer_.get());
798
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()) {
804       DoWrite(context);
805       return;
806     }
807   }
808
809   if (net_result >= 0)
810     SendWriteReply(context, write_buffer_->BytesConsumed());
811   else
812     SendWriteReply(context, NetErrorToPepperError(net_result));
813
814   write_buffer_ = NULL;
815   write_buffer_base_ = NULL;
816 }
817
818 void PepperTCPSocketMessageFilter::OnAcceptCompleted(
819     const ppapi::host::ReplyMessageContext& context,
820     int net_result) {
821   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
822   DCHECK(pending_accept_);
823
824   pending_accept_ = false;
825
826   if (net_result != net::OK) {
827     SendAcceptError(context, NetErrorToPepperError(net_result));
828     return;
829   }
830
831   DCHECK(accepted_socket_.get());
832
833   net::IPEndPoint ip_end_point_local;
834   PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
835   PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
836
837   int32_t pp_result =
838       NetErrorToPepperError(accepted_socket_->GetLocalAddress(
839           &ip_end_point_local));
840   if (pp_result != PP_OK) {
841     SendAcceptError(context, pp_result);
842     return;
843   }
844   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
845           ip_end_point_local.address(),
846           ip_end_point_local.port(),
847           &local_addr) ||
848       !NetAddressPrivateImpl::IPEndPointToNetAddress(
849           accepted_address_.address(),
850           accepted_address_.port(),
851           &remote_addr)) {
852     SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
853     return;
854   }
855
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
858   // LISTENING state.
859   scoped_ptr<ppapi::host::ResourceHost> host =
860       factory_->CreateAcceptedTCPSocket(
861           instance_, version_, accepted_socket_.Pass());
862   if (!host) {
863     SendAcceptError(context, PP_ERROR_NOSPACE);
864     return;
865   }
866   int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
867   if (pending_host_id)
868     SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
869   else
870     SendAcceptError(context, PP_ERROR_NOSPACE);
871 }
872
873 void PepperTCPSocketMessageFilter::SendBindReply(
874     const ppapi::host::ReplyMessageContext& context,
875     int32_t pp_result,
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));
880 }
881
882 void PepperTCPSocketMessageFilter::SendBindError(
883     const ppapi::host::ReplyMessageContext& context,
884     int32_t pp_error) {
885   SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
886 }
887
888 void PepperTCPSocketMessageFilter::SendConnectReply(
889     const ppapi::host::ReplyMessageContext& context,
890     int32_t pp_result,
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));
897 }
898
899 void PepperTCPSocketMessageFilter::SendConnectError(
900     const ppapi::host::ReplyMessageContext& context,
901     int32_t pp_error) {
902   SendConnectReply(context,
903                    pp_error,
904                    NetAddressPrivateImpl::kInvalidNetAddress,
905                    NetAddressPrivateImpl::kInvalidNetAddress);
906 }
907
908 void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
909     const ppapi::host::ReplyMessageContext& context,
910     int32_t pp_result) {
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);
921     }
922   }
923   SendReply(reply_context,
924             PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
925 }
926
927 void PepperTCPSocketMessageFilter::SendReadReply(
928     const ppapi::host::ReplyMessageContext& context,
929     int32_t pp_result,
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));
934 }
935
936 void PepperTCPSocketMessageFilter::SendReadError(
937     const ppapi::host::ReplyMessageContext& context,
938     int32_t pp_error) {
939   SendReadReply(context, pp_error, std::string());
940 }
941
942 void PepperTCPSocketMessageFilter::SendWriteReply(
943     const ppapi::host::ReplyMessageContext& context,
944     int32_t pp_result) {
945   ppapi::host::ReplyMessageContext reply_context(context);
946   reply_context.params.set_result(pp_result);
947   SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
948 }
949
950 void PepperTCPSocketMessageFilter::SendListenReply(
951     const ppapi::host::ReplyMessageContext& context,
952     int32_t pp_result) {
953   ppapi::host::ReplyMessageContext reply_context(context);
954   reply_context.params.set_result(pp_result);
955   SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
956 }
957
958 void PepperTCPSocketMessageFilter::SendAcceptReply(
959     const ppapi::host::ReplyMessageContext& context,
960     int32_t pp_result,
961     int pending_host_id,
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));
969 }
970
971 void PepperTCPSocketMessageFilter::SendAcceptError(
972     const ppapi::host::ReplyMessageContext& context,
973     int32_t pp_error) {
974   SendAcceptReply(context, pp_error, 0,
975                   NetAddressPrivateImpl::kInvalidNetAddress,
976                   NetAddressPrivateImpl::kInvalidNetAddress);
977 }
978
979 }  // namespace content