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
37using ppapi::NetAddressPrivateImpl;
38using ppapi::host::NetErrorToPepperError;
39using ppapi::proxy::TCPSocketResourceBase;
40using ppapi::TCPSocketState;
41using ppapi::TCPSocketVersion;
42
43namespace {
44
45size_t g_num_instances = 0;
46
47}  // namespace
48
49namespace content {
50
51PepperTCPSocketMessageFilter::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_frame_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->GetRenderFrameIDsForInstance(
73          instance, &render_process_id_, &render_frame_id_)) {
74    NOTREACHED();
75  }
76}
77
78PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
79    BrowserPpapiHostImpl* host,
80    PP_Instance instance,
81    TCPSocketVersion version,
82    scoped_ptr<net::TCPSocket> socket)
83    : version_(version),
84      external_plugin_(host->external_plugin()),
85      render_process_id_(0),
86      render_frame_id_(0),
87      ppapi_host_(host->GetPpapiHost()),
88      factory_(NULL),
89      instance_(instance),
90      state_(TCPSocketState::CONNECTED),
91      end_of_file_reached_(false),
92      bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
93      address_index_(0),
94      socket_(socket.Pass()),
95      ssl_context_helper_(host->ssl_context_helper()),
96      pending_accept_(false) {
97  DCHECK(host);
98  DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
99
100  ++g_num_instances;
101  if (!host->GetRenderFrameIDsForInstance(
102          instance, &render_process_id_, &render_frame_id_)) {
103    NOTREACHED();
104  }
105}
106
107PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
108  if (socket_)
109    socket_->Close();
110  if (ssl_socket_)
111    ssl_socket_->Disconnect();
112  --g_num_instances;
113}
114
115// static
116size_t PepperTCPSocketMessageFilter::GetNumInstances() {
117  return g_num_instances;
118}
119
120scoped_refptr<base::TaskRunner>
121PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
122    const IPC::Message& message) {
123  switch (message.type()) {
124    case PpapiHostMsg_TCPSocket_Bind::ID:
125    case PpapiHostMsg_TCPSocket_Connect::ID:
126    case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
127    case PpapiHostMsg_TCPSocket_Listen::ID:
128      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
129    case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
130    case PpapiHostMsg_TCPSocket_Read::ID:
131    case PpapiHostMsg_TCPSocket_Write::ID:
132    case PpapiHostMsg_TCPSocket_Accept::ID:
133    case PpapiHostMsg_TCPSocket_Close::ID:
134    case PpapiHostMsg_TCPSocket_SetOption::ID:
135      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
136  }
137  return NULL;
138}
139
140int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
141    const IPC::Message& msg,
142    ppapi::host::HostMessageContext* context) {
143  PPAPI_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
144    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
145    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Connect,
146                                      OnMsgConnect)
147    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
148        PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
149        OnMsgConnectWithNetAddress)
150    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SSLHandshake,
151                                      OnMsgSSLHandshake)
152    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Read, OnMsgRead)
153    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
154    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Listen,
155                                      OnMsgListen)
156    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Accept,
157                                        OnMsgAccept)
158    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Close,
159                                        OnMsgClose)
160    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SetOption,
161                                      OnMsgSetOption)
162  PPAPI_END_MESSAGE_MAP()
163  return PP_ERROR_FAILED;
164}
165
166int32_t PepperTCPSocketMessageFilter::OnMsgBind(
167    const ppapi::host::HostMessageContext* context,
168    const PP_NetAddress_Private& net_addr) {
169  DCHECK_CURRENTLY_ON(BrowserThread::UI);
170
171  // This is only supported by PPB_TCPSocket v1.1 or above.
172  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
173    NOTREACHED();
174    return PP_ERROR_NOACCESS;
175  }
176
177  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
178                                             false /* private_api */,
179                                             NULL,
180                                             render_process_id_,
181                                             render_frame_id_)) {
182    return PP_ERROR_NOACCESS;
183  }
184
185  bind_input_addr_ = net_addr;
186
187  BrowserThread::PostTask(BrowserThread::IO,
188                          FROM_HERE,
189                          base::Bind(&PepperTCPSocketMessageFilter::DoBind,
190                                     this,
191                                     context->MakeReplyMessageContext(),
192                                     net_addr));
193  return PP_OK_COMPLETIONPENDING;
194}
195
196int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
197    const ppapi::host::HostMessageContext* context,
198    const std::string& host,
199    uint16_t port) {
200  DCHECK_CURRENTLY_ON(BrowserThread::UI);
201
202  // This is only supported by PPB_TCPSocket_Private.
203  if (!IsPrivateAPI()) {
204    NOTREACHED();
205    return PP_ERROR_NOACCESS;
206  }
207
208  SocketPermissionRequest request(
209      SocketPermissionRequest::TCP_CONNECT, host, port);
210  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
211                                             true /* private_api */,
212                                             &request,
213                                             render_process_id_,
214                                             render_frame_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(BrowserThread::IO,
227                          FROM_HERE,
228                          base::Bind(&PepperTCPSocketMessageFilter::DoConnect,
229                                     this,
230                                     context->MakeReplyMessageContext(),
231                                     host,
232                                     port,
233                                     browser_context->GetResourceContext()));
234  return PP_OK_COMPLETIONPENDING;
235}
236
237int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
238    const ppapi::host::HostMessageContext* context,
239    const PP_NetAddress_Private& net_addr) {
240  DCHECK_CURRENTLY_ON(BrowserThread::UI);
241
242  content::SocketPermissionRequest request =
243      pepper_socket_utils::CreateSocketPermissionRequest(
244          content::SocketPermissionRequest::TCP_CONNECT, net_addr);
245  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
246                                             IsPrivateAPI(),
247                                             &request,
248                                             render_process_id_,
249                                             render_frame_id_)) {
250    return PP_ERROR_NOACCESS;
251  }
252
253  BrowserThread::PostTask(
254      BrowserThread::IO,
255      FROM_HERE,
256      base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress,
257                 this,
258                 context->MakeReplyMessageContext(),
259                 net_addr));
260  return PP_OK_COMPLETIONPENDING;
261}
262
263int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
264    const ppapi::host::HostMessageContext* context,
265    const std::string& server_name,
266    uint16_t server_port,
267    const std::vector<std::vector<char> >& trusted_certs,
268    const std::vector<std::vector<char> >& untrusted_certs) {
269  DCHECK_CURRENTLY_ON(BrowserThread::IO);
270
271  // Allow to do SSL handshake only if currently the socket has been connected
272  // and there isn't pending read or write.
273  if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
274      read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
275    return PP_ERROR_FAILED;
276  }
277
278  // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
279  net::IPEndPoint peer_address;
280  if (socket_->GetPeerAddress(&peer_address) != net::OK)
281    return PP_ERROR_FAILED;
282
283  scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
284  handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
285      new net::TCPClientSocket(socket_.Pass(), peer_address)));
286  net::ClientSocketFactory* factory =
287      net::ClientSocketFactory::GetDefaultFactory();
288  net::HostPortPair host_port_pair(server_name, server_port);
289  net::SSLClientSocketContext ssl_context;
290  ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
291  ssl_context.transport_security_state =
292      ssl_context_helper_->GetTransportSecurityState();
293  ssl_socket_ =
294      factory->CreateSSLClientSocket(handle.Pass(),
295                                     host_port_pair,
296                                     ssl_context_helper_->ssl_config(),
297                                     ssl_context);
298  if (!ssl_socket_) {
299    LOG(WARNING) << "Failed to create an SSL client socket.";
300    state_.CompletePendingTransition(false);
301    return PP_ERROR_FAILED;
302  }
303
304  state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
305
306  const ppapi::host::ReplyMessageContext reply_context(
307      context->MakeReplyMessageContext());
308  int net_result = ssl_socket_->Connect(
309      base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
310                 base::Unretained(this),
311                 reply_context));
312  if (net_result != net::ERR_IO_PENDING)
313    OnSSLHandshakeCompleted(reply_context, net_result);
314  return PP_OK_COMPLETIONPENDING;
315}
316
317int32_t PepperTCPSocketMessageFilter::OnMsgRead(
318    const ppapi::host::HostMessageContext* context,
319    int32_t bytes_to_read) {
320  DCHECK_CURRENTLY_ON(BrowserThread::IO);
321  if (!state_.IsConnected() || end_of_file_reached_)
322    return PP_ERROR_FAILED;
323  if (read_buffer_.get())
324    return PP_ERROR_INPROGRESS;
325  if (bytes_to_read <= 0 ||
326      bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
327    return PP_ERROR_BADARGUMENT;
328  }
329
330  ppapi::host::ReplyMessageContext reply_context(
331      context->MakeReplyMessageContext());
332  read_buffer_ = new net::IOBuffer(bytes_to_read);
333
334  int net_result = net::ERR_FAILED;
335  if (socket_) {
336    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
337    net_result =
338        socket_->Read(read_buffer_.get(),
339                      bytes_to_read,
340                      base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
341                                 base::Unretained(this),
342                                 reply_context));
343  } else if (ssl_socket_) {
344    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
345    net_result = ssl_socket_->Read(
346        read_buffer_.get(),
347        bytes_to_read,
348        base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
349                   base::Unretained(this),
350                   reply_context));
351  }
352  if (net_result != net::ERR_IO_PENDING)
353    OnReadCompleted(reply_context, net_result);
354  return PP_OK_COMPLETIONPENDING;
355}
356
357int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
358    const ppapi::host::HostMessageContext* context,
359    const std::string& data) {
360  DCHECK_CURRENTLY_ON(BrowserThread::IO);
361
362  if (!state_.IsConnected())
363    return PP_ERROR_FAILED;
364  if (write_buffer_base_.get() || write_buffer_.get())
365    return PP_ERROR_INPROGRESS;
366
367  size_t data_size = data.size();
368  if (data_size == 0 ||
369      data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
370    return PP_ERROR_BADARGUMENT;
371  }
372
373  write_buffer_base_ = new net::IOBuffer(data_size);
374  memcpy(write_buffer_base_->data(), data.data(), data_size);
375  write_buffer_ =
376      new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
377  DoWrite(context->MakeReplyMessageContext());
378  return PP_OK_COMPLETIONPENDING;
379}
380
381int32_t PepperTCPSocketMessageFilter::OnMsgListen(
382    const ppapi::host::HostMessageContext* context,
383    int32_t backlog) {
384  DCHECK_CURRENTLY_ON(BrowserThread::UI);
385
386  // This is only supported by PPB_TCPSocket v1.1 or above.
387  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
388    NOTREACHED();
389    return PP_ERROR_NOACCESS;
390  }
391
392  content::SocketPermissionRequest request =
393      pepper_socket_utils::CreateSocketPermissionRequest(
394          content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
395  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
396                                             false /* private_api */,
397                                             &request,
398                                             render_process_id_,
399                                             render_frame_id_)) {
400    return PP_ERROR_NOACCESS;
401  }
402
403  BrowserThread::PostTask(BrowserThread::IO,
404                          FROM_HERE,
405                          base::Bind(&PepperTCPSocketMessageFilter::DoListen,
406                                     this,
407                                     context->MakeReplyMessageContext(),
408                                     backlog));
409  return PP_OK_COMPLETIONPENDING;
410}
411
412int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
413    const ppapi::host::HostMessageContext* context) {
414  DCHECK_CURRENTLY_ON(BrowserThread::IO);
415
416  if (pending_accept_)
417    return PP_ERROR_INPROGRESS;
418  if (state_.state() != TCPSocketState::LISTENING)
419    return PP_ERROR_FAILED;
420
421  pending_accept_ = true;
422  ppapi::host::ReplyMessageContext reply_context(
423      context->MakeReplyMessageContext());
424  int net_result = socket_->Accept(
425      &accepted_socket_,
426      &accepted_address_,
427      base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
428                 base::Unretained(this),
429                 reply_context));
430  if (net_result != net::ERR_IO_PENDING)
431    OnAcceptCompleted(reply_context, net_result);
432  return PP_OK_COMPLETIONPENDING;
433}
434
435int32_t PepperTCPSocketMessageFilter::OnMsgClose(
436    const ppapi::host::HostMessageContext* context) {
437  DCHECK_CURRENTLY_ON(BrowserThread::IO);
438  if (state_.state() == TCPSocketState::CLOSED)
439    return PP_OK;
440
441  state_.DoTransition(TCPSocketState::CLOSE, true);
442  // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
443  if (socket_) {
444    socket_->Close();
445  } else if (ssl_socket_) {
446    ssl_socket_->Disconnect();
447  }
448  return PP_OK;
449}
450
451int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
452    const ppapi::host::HostMessageContext* context,
453    PP_TCPSocket_Option name,
454    const ppapi::SocketOptionData& value) {
455  DCHECK_CURRENTLY_ON(BrowserThread::IO);
456
457  switch (name) {
458    case PP_TCPSOCKET_OPTION_NO_DELAY: {
459      if (state_.state() != TCPSocketState::CONNECTED)
460        return PP_ERROR_FAILED;
461
462      bool boolean_value = false;
463      if (!value.GetBool(&boolean_value))
464        return PP_ERROR_BADARGUMENT;
465      return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
466    }
467    case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
468    case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
469      if (state_.state() != TCPSocketState::CONNECTED)
470        return PP_ERROR_FAILED;
471
472      int32_t integer_value = 0;
473      if (!value.GetInt32(&integer_value) || integer_value <= 0)
474        return PP_ERROR_BADARGUMENT;
475
476      int net_result = net::ERR_UNEXPECTED;
477      if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
478        if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
479          return PP_ERROR_BADARGUMENT;
480        net_result = socket_->SetSendBufferSize(integer_value);
481      } else {
482        if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
483          return PP_ERROR_BADARGUMENT;
484        net_result = socket_->SetReceiveBufferSize(integer_value);
485      }
486      // TODO(wtc): Add error mapping code.
487      return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED;
488    }
489    default: {
490      NOTREACHED();
491      return PP_ERROR_BADARGUMENT;
492    }
493  }
494}
495
496void PepperTCPSocketMessageFilter::DoBind(
497    const ppapi::host::ReplyMessageContext& context,
498    const PP_NetAddress_Private& net_addr) {
499  DCHECK_CURRENTLY_ON(BrowserThread::IO);
500
501  if (state_.IsPending(TCPSocketState::BIND)) {
502    SendBindError(context, PP_ERROR_INPROGRESS);
503    return;
504  }
505  if (!state_.IsValidTransition(TCPSocketState::BIND)) {
506    SendBindError(context, PP_ERROR_FAILED);
507    return;
508  }
509
510  int pp_result = PP_OK;
511  do {
512    net::IPAddressNumber address;
513    int port;
514    if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
515            net_addr, &address, &port)) {
516      pp_result = PP_ERROR_ADDRESS_INVALID;
517      break;
518    }
519    net::IPEndPoint bind_addr(address, port);
520
521    DCHECK(!socket_->IsValid());
522    pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
523    if (pp_result != PP_OK)
524      break;
525
526    pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
527    if (pp_result != PP_OK)
528      break;
529
530    pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
531    if (pp_result != PP_OK)
532      break;
533
534    net::IPEndPoint ip_end_point_local;
535    pp_result =
536        NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
537    if (pp_result != PP_OK)
538      break;
539
540    PP_NetAddress_Private local_addr =
541        NetAddressPrivateImpl::kInvalidNetAddress;
542    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
543            ip_end_point_local.address(),
544            ip_end_point_local.port(),
545            &local_addr)) {
546      pp_result = PP_ERROR_ADDRESS_INVALID;
547      break;
548    }
549
550    SendBindReply(context, PP_OK, local_addr);
551    state_.DoTransition(TCPSocketState::BIND, true);
552    return;
553  } while (false);
554  if (socket_->IsValid())
555    socket_->Close();
556  SendBindError(context, pp_result);
557  state_.DoTransition(TCPSocketState::BIND, false);
558}
559
560void PepperTCPSocketMessageFilter::DoConnect(
561    const ppapi::host::ReplyMessageContext& context,
562    const std::string& host,
563    uint16_t port,
564    ResourceContext* resource_context) {
565  DCHECK_CURRENTLY_ON(BrowserThread::IO);
566
567  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
568    SendConnectError(context, PP_ERROR_FAILED);
569    return;
570  }
571
572  state_.SetPendingTransition(TCPSocketState::CONNECT);
573  address_index_ = 0;
574  address_list_.clear();
575  net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
576  resolver_.reset(
577      new net::SingleRequestHostResolver(resource_context->GetHostResolver()));
578  int net_result = resolver_->Resolve(
579      request_info,
580      net::DEFAULT_PRIORITY,
581      &address_list_,
582      base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
583                 base::Unretained(this),
584                 context),
585      net::BoundNetLog());
586  if (net_result != net::ERR_IO_PENDING)
587    OnResolveCompleted(context, net_result);
588}
589
590void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
591    const ppapi::host::ReplyMessageContext& context,
592    const PP_NetAddress_Private& net_addr) {
593  DCHECK_CURRENTLY_ON(BrowserThread::IO);
594
595  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
596    SendConnectError(context, PP_ERROR_FAILED);
597    return;
598  }
599
600  state_.SetPendingTransition(TCPSocketState::CONNECT);
601
602  net::IPAddressNumber address;
603  int port;
604  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
605          net_addr, &address, &port)) {
606    state_.CompletePendingTransition(false);
607    SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
608    return;
609  }
610
611  // Copy the single IPEndPoint to address_list_.
612  address_index_ = 0;
613  address_list_.clear();
614  address_list_.push_back(net::IPEndPoint(address, port));
615  StartConnect(context);
616}
617
618void PepperTCPSocketMessageFilter::DoWrite(
619    const ppapi::host::ReplyMessageContext& context) {
620  DCHECK_CURRENTLY_ON(BrowserThread::IO);
621  DCHECK(write_buffer_base_.get());
622  DCHECK(write_buffer_.get());
623  DCHECK_GT(write_buffer_->BytesRemaining(), 0);
624  DCHECK(state_.IsConnected());
625
626  int net_result = net::ERR_FAILED;
627  if (socket_) {
628    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
629    net_result = socket_->Write(
630        write_buffer_.get(),
631        write_buffer_->BytesRemaining(),
632        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
633                   base::Unretained(this),
634                   context));
635  } else if (ssl_socket_) {
636    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
637    net_result = ssl_socket_->Write(
638        write_buffer_.get(),
639        write_buffer_->BytesRemaining(),
640        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
641                   base::Unretained(this),
642                   context));
643  }
644  if (net_result != net::ERR_IO_PENDING)
645    OnWriteCompleted(context, net_result);
646}
647
648void PepperTCPSocketMessageFilter::DoListen(
649    const ppapi::host::ReplyMessageContext& context,
650    int32_t backlog) {
651  DCHECK_CURRENTLY_ON(BrowserThread::IO);
652
653  if (state_.IsPending(TCPSocketState::LISTEN)) {
654    SendListenReply(context, PP_ERROR_INPROGRESS);
655    return;
656  }
657  if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
658    SendListenReply(context, PP_ERROR_FAILED);
659    return;
660  }
661
662  int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
663  SendListenReply(context, pp_result);
664  state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
665}
666
667void PepperTCPSocketMessageFilter::OnResolveCompleted(
668    const ppapi::host::ReplyMessageContext& context,
669    int net_result) {
670  DCHECK_CURRENTLY_ON(BrowserThread::IO);
671
672  if (!state_.IsPending(TCPSocketState::CONNECT)) {
673    DCHECK(state_.state() == TCPSocketState::CLOSED);
674    SendConnectError(context, PP_ERROR_FAILED);
675    return;
676  }
677
678  if (net_result != net::OK) {
679    SendConnectError(context, NetErrorToPepperError(net_result));
680    state_.CompletePendingTransition(false);
681    return;
682  }
683
684  StartConnect(context);
685}
686
687void PepperTCPSocketMessageFilter::StartConnect(
688    const ppapi::host::ReplyMessageContext& context) {
689  DCHECK_CURRENTLY_ON(BrowserThread::IO);
690  DCHECK(state_.IsPending(TCPSocketState::CONNECT));
691  DCHECK_LT(address_index_, address_list_.size());
692
693  int net_result = net::OK;
694  if (!socket_->IsValid())
695    net_result = socket_->Open(address_list_[address_index_].GetFamily());
696
697  if (net_result == net::OK) {
698    net_result = socket_->Connect(
699        address_list_[address_index_],
700        base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
701                   base::Unretained(this),
702                   context));
703  }
704  if (net_result != net::ERR_IO_PENDING)
705    OnConnectCompleted(context, net_result);
706}
707
708void PepperTCPSocketMessageFilter::OnConnectCompleted(
709    const ppapi::host::ReplyMessageContext& context,
710    int net_result) {
711  DCHECK_CURRENTLY_ON(BrowserThread::IO);
712
713  if (!state_.IsPending(TCPSocketState::CONNECT)) {
714    DCHECK(state_.state() == TCPSocketState::CLOSED);
715    SendConnectError(context, PP_ERROR_FAILED);
716    return;
717  }
718
719  int32_t pp_result = NetErrorToPepperError(net_result);
720  do {
721    if (pp_result != PP_OK)
722      break;
723
724    net::IPEndPoint ip_end_point_local;
725    net::IPEndPoint ip_end_point_remote;
726    pp_result =
727        NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
728    if (pp_result != PP_OK)
729      break;
730    pp_result =
731        NetErrorToPepperError(socket_->GetPeerAddress(&ip_end_point_remote));
732    if (pp_result != PP_OK)
733      break;
734
735    PP_NetAddress_Private local_addr =
736        NetAddressPrivateImpl::kInvalidNetAddress;
737    PP_NetAddress_Private remote_addr =
738        NetAddressPrivateImpl::kInvalidNetAddress;
739    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
740            ip_end_point_local.address(),
741            ip_end_point_local.port(),
742            &local_addr) ||
743        !NetAddressPrivateImpl::IPEndPointToNetAddress(
744            ip_end_point_remote.address(),
745            ip_end_point_remote.port(),
746            &remote_addr)) {
747      pp_result = PP_ERROR_ADDRESS_INVALID;
748      break;
749    }
750
751    socket_->SetDefaultOptionsForClient();
752    SendConnectReply(context, PP_OK, local_addr, remote_addr);
753    state_.CompletePendingTransition(true);
754    return;
755  } while (false);
756
757  if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
758    DCHECK_EQ(1u, address_list_.size());
759
760    SendConnectError(context, pp_result);
761    state_.CompletePendingTransition(false);
762  } else {
763    // We have to recreate |socket_| because it doesn't allow a second connect
764    // attempt. We won't lose any state such as bound address or set options,
765    // because in the private or v1.0 API, connect must be the first operation.
766    socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
767
768    if (address_index_ + 1 < address_list_.size()) {
769      DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
770      address_index_++;
771      StartConnect(context);
772    } else {
773      SendConnectError(context, pp_result);
774      // In order to maintain backward compatibility, allow further attempts to
775      // connect the socket.
776      state_ = TCPSocketState(TCPSocketState::INITIAL);
777    }
778  }
779}
780
781void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
782    const ppapi::host::ReplyMessageContext& context,
783    int net_result) {
784  DCHECK_CURRENTLY_ON(BrowserThread::IO);
785
786  if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
787    DCHECK(state_.state() == TCPSocketState::CLOSED);
788    SendSSLHandshakeReply(context, PP_ERROR_FAILED);
789    return;
790  }
791
792  SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
793  state_.CompletePendingTransition(net_result == net::OK);
794}
795
796void PepperTCPSocketMessageFilter::OnReadCompleted(
797    const ppapi::host::ReplyMessageContext& context,
798    int net_result) {
799  DCHECK_CURRENTLY_ON(BrowserThread::IO);
800  DCHECK(read_buffer_.get());
801
802  if (net_result > 0) {
803    SendReadReply(
804        context, PP_OK, std::string(read_buffer_->data(), net_result));
805  } else if (net_result == 0) {
806    end_of_file_reached_ = true;
807    SendReadReply(context, PP_OK, std::string());
808  } else {
809    SendReadError(context, NetErrorToPepperError(net_result));
810  }
811  read_buffer_ = NULL;
812}
813
814void PepperTCPSocketMessageFilter::OnWriteCompleted(
815    const ppapi::host::ReplyMessageContext& context,
816    int net_result) {
817  DCHECK_CURRENTLY_ON(BrowserThread::IO);
818  DCHECK(write_buffer_base_.get());
819  DCHECK(write_buffer_.get());
820
821  // Note: For partial writes of 0 bytes, don't continue writing to avoid a
822  // likely infinite loop.
823  if (net_result > 0) {
824    write_buffer_->DidConsume(net_result);
825    if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
826      DoWrite(context);
827      return;
828    }
829  }
830
831  if (net_result >= 0)
832    SendWriteReply(context, write_buffer_->BytesConsumed());
833  else
834    SendWriteReply(context, NetErrorToPepperError(net_result));
835
836  write_buffer_ = NULL;
837  write_buffer_base_ = NULL;
838}
839
840void PepperTCPSocketMessageFilter::OnAcceptCompleted(
841    const ppapi::host::ReplyMessageContext& context,
842    int net_result) {
843  DCHECK_CURRENTLY_ON(BrowserThread::IO);
844  DCHECK(pending_accept_);
845
846  pending_accept_ = false;
847
848  if (net_result != net::OK) {
849    SendAcceptError(context, NetErrorToPepperError(net_result));
850    return;
851  }
852
853  DCHECK(accepted_socket_.get());
854
855  net::IPEndPoint ip_end_point_local;
856  PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
857  PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
858
859  int32_t pp_result = NetErrorToPepperError(
860      accepted_socket_->GetLocalAddress(&ip_end_point_local));
861  if (pp_result != PP_OK) {
862    SendAcceptError(context, pp_result);
863    return;
864  }
865  if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
866          ip_end_point_local.address(),
867          ip_end_point_local.port(),
868          &local_addr) ||
869      !NetAddressPrivateImpl::IPEndPointToNetAddress(
870          accepted_address_.address(),
871          accepted_address_.port(),
872          &remote_addr)) {
873    SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
874    return;
875  }
876
877  // |factory_| is guaranteed to be non-NULL here. Only those instances created
878  // in CONNECTED state have a NULL |factory_|, while getting here requires
879  // LISTENING state.
880  scoped_ptr<ppapi::host::ResourceHost> host =
881      factory_->CreateAcceptedTCPSocket(
882          instance_, version_, accepted_socket_.Pass());
883  if (!host) {
884    SendAcceptError(context, PP_ERROR_NOSPACE);
885    return;
886  }
887  int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
888  if (pending_host_id)
889    SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
890  else
891    SendAcceptError(context, PP_ERROR_NOSPACE);
892}
893
894void PepperTCPSocketMessageFilter::SendBindReply(
895    const ppapi::host::ReplyMessageContext& context,
896    int32_t pp_result,
897    const PP_NetAddress_Private& local_addr) {
898  ppapi::host::ReplyMessageContext reply_context(context);
899  reply_context.params.set_result(pp_result);
900  SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
901}
902
903void PepperTCPSocketMessageFilter::SendBindError(
904    const ppapi::host::ReplyMessageContext& context,
905    int32_t pp_error) {
906  SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
907}
908
909void PepperTCPSocketMessageFilter::SendConnectReply(
910    const ppapi::host::ReplyMessageContext& context,
911    int32_t pp_result,
912    const PP_NetAddress_Private& local_addr,
913    const PP_NetAddress_Private& remote_addr) {
914  ppapi::host::ReplyMessageContext reply_context(context);
915  reply_context.params.set_result(pp_result);
916  SendReply(reply_context,
917            PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
918}
919
920void PepperTCPSocketMessageFilter::SendConnectError(
921    const ppapi::host::ReplyMessageContext& context,
922    int32_t pp_error) {
923  SendConnectReply(context,
924                   pp_error,
925                   NetAddressPrivateImpl::kInvalidNetAddress,
926                   NetAddressPrivateImpl::kInvalidNetAddress);
927}
928
929void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
930    const ppapi::host::ReplyMessageContext& context,
931    int32_t pp_result) {
932  ppapi::host::ReplyMessageContext reply_context(context);
933  reply_context.params.set_result(pp_result);
934  ppapi::PPB_X509Certificate_Fields certificate_fields;
935  if (pp_result == PP_OK) {
936    // Our socket is guaranteed to be an SSL socket if we get here.
937    net::SSLInfo ssl_info;
938    ssl_socket_->GetSSLInfo(&ssl_info);
939    if (ssl_info.cert.get()) {
940      pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
941                                                &certificate_fields);
942    }
943  }
944  SendReply(reply_context,
945            PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
946}
947
948void PepperTCPSocketMessageFilter::SendReadReply(
949    const ppapi::host::ReplyMessageContext& context,
950    int32_t pp_result,
951    const std::string& data) {
952  ppapi::host::ReplyMessageContext reply_context(context);
953  reply_context.params.set_result(pp_result);
954  SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
955}
956
957void PepperTCPSocketMessageFilter::SendReadError(
958    const ppapi::host::ReplyMessageContext& context,
959    int32_t pp_error) {
960  SendReadReply(context, pp_error, std::string());
961}
962
963void PepperTCPSocketMessageFilter::SendWriteReply(
964    const ppapi::host::ReplyMessageContext& context,
965    int32_t pp_result) {
966  ppapi::host::ReplyMessageContext reply_context(context);
967  reply_context.params.set_result(pp_result);
968  SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
969}
970
971void PepperTCPSocketMessageFilter::SendListenReply(
972    const ppapi::host::ReplyMessageContext& context,
973    int32_t pp_result) {
974  ppapi::host::ReplyMessageContext reply_context(context);
975  reply_context.params.set_result(pp_result);
976  SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
977}
978
979void PepperTCPSocketMessageFilter::SendAcceptReply(
980    const ppapi::host::ReplyMessageContext& context,
981    int32_t pp_result,
982    int pending_host_id,
983    const PP_NetAddress_Private& local_addr,
984    const PP_NetAddress_Private& remote_addr) {
985  ppapi::host::ReplyMessageContext reply_context(context);
986  reply_context.params.set_result(pp_result);
987  SendReply(reply_context,
988            PpapiPluginMsg_TCPSocket_AcceptReply(
989                pending_host_id, local_addr, remote_addr));
990}
991
992void PepperTCPSocketMessageFilter::SendAcceptError(
993    const ppapi::host::ReplyMessageContext& context,
994    int32_t pp_error) {
995  SendAcceptReply(context,
996                  pp_error,
997                  0,
998                  NetAddressPrivateImpl::kInvalidNetAddress,
999                  NetAddressPrivateImpl::kInvalidNetAddress);
1000}
1001
1002}  // namespace content
1003