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_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
79PepperTCPSocketMessageFilter::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
109PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
110  if (socket_)
111    socket_->Close();
112  if (ssl_socket_)
113    ssl_socket_->Disconnect();
114  --g_num_instances;
115}
116
117// static
118size_t PepperTCPSocketMessageFilter::GetNumInstances() {
119  return g_num_instances;
120}
121
122scoped_refptr<base::TaskRunner>
123PepperTCPSocketMessageFilter::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
142int32_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
171int32_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
197int32_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
234int32_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
255int32_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
306int32_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
344int32_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
368int32_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
395int32_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
417int32_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
433int32_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
477void 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
541void 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
570void 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
598void 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
626void 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
645void 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
665void 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
685void 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
758void 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
773void 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
792void 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
818void 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
873void 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
882void PepperTCPSocketMessageFilter::SendBindError(
883    const ppapi::host::ReplyMessageContext& context,
884    int32_t pp_error) {
885  SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
886}
887
888void 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
899void 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
908void 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
927void 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
936void PepperTCPSocketMessageFilter::SendReadError(
937    const ppapi::host::ReplyMessageContext& context,
938    int32_t pp_error) {
939  SendReadReply(context, pp_error, std::string());
940}
941
942void 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
950void 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
958void 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
971void 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
980