1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file.
4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <cstring>
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/bind.h"
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/logging.h"
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "build/build_config.h"
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/browser/browser_context.h"
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/browser/resource_context.h"
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/common/socket_permission_request.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/base/address_family.h"
21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/host_port_pair.h"
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/io_buffer.h"
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/net_errors.h"
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/dns/single_request_host_resolver.h"
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/client_socket_handle.h"
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/ssl_client_socket.h"
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/tcp_client_socket.h"
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/host/dispatch_host_message.h"
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/host/error_conversion.h"
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ppapi/host/ppapi_host.h"
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ppapi/host/resource_host.h"
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/proxy/tcp_socket_resource_base.h"
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/shared_impl/private/net_address_private_impl.h"
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using ppapi::NetAddressPrivateImpl;
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using ppapi::host::NetErrorToPepperError;
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using ppapi::proxy::TCPSocketResourceBase;
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)using ppapi::TCPSocketState;
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)using ppapi::TCPSocketVersion;
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace {
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)size_t g_num_instances = 0;
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace content {
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ContentBrowserPepperHostFactory* factory,
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    BrowserPpapiHostImpl* host,
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_Instance instance,
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    TCPSocketVersion version)
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : version_(version),
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      external_plugin_(host->external_plugin()),
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      render_process_id_(0),
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_frame_id_(0),
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ppapi_host_(host->GetPpapiHost()),
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      factory_(factory),
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      instance_(instance),
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_(TCPSocketState::INITIAL),
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      end_of_file_reached_(false),
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      address_index_(0),
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      socket_(new net::TCPSocket(NULL, net::NetLog::Source())),
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ssl_context_helper_(host->ssl_context_helper()),
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pending_accept_(false) {
70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(host);
71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ++g_num_instances;
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!host->GetRenderFrameIDsForInstance(
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          instance, &render_process_id_, &render_frame_id_)) {
74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    NOTREACHED();
75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    BrowserPpapiHostImpl* host,
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_Instance instance,
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    TCPSocketVersion version,
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_ptr<net::TCPSocket> socket)
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : version_(version),
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      external_plugin_(host->external_plugin()),
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      render_process_id_(0),
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_frame_id_(0),
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ppapi_host_(host->GetPpapiHost()),
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      factory_(NULL),
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      instance_(instance),
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_(TCPSocketState::CONNECTED),
91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      end_of_file_reached_(false),
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      address_index_(0),
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      socket_(socket.Pass()),
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ssl_context_helper_(host->ssl_context_helper()),
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pending_accept_(false) {
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(host);
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ++g_num_instances;
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!host->GetRenderFrameIDsForInstance(
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          instance, &render_process_id_, &render_frame_id_)) {
103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    NOTREACHED();
104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (socket_)
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_->Close();
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (ssl_socket_)
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ssl_socket_->Disconnect();
112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  --g_num_instances;
113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// static
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)size_t PepperTCPSocketMessageFilter::GetNumInstances() {
117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return g_num_instances;
118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)scoped_refptr<base::TaskRunner>
121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const IPC::Message& message) {
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (message.type()) {
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_Bind::ID:
125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_Connect::ID:
126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_Listen::ID:
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_Read::ID:
131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_Write::ID:
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_Accept::ID:
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_Close::ID:
134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PpapiHostMsg_TCPSocket_SetOption::ID:
135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return NULL;
138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const IPC::Message& msg,
142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ppapi::host::HostMessageContext* context) {
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Connect,
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnMsgConnect)
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        OnMsgConnectWithNetAddress)
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SSLHandshake,
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnMsgSSLHandshake)
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Read, OnMsgRead)
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Listen,
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnMsgListen)
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Accept,
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        OnMsgAccept)
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Close,
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        OnMsgClose)
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SetOption,
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      OnMsgSetOption)
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PPAPI_END_MESSAGE_MAP()
163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_ERROR_FAILED;
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgBind(
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // This is only supported by PPB_TCPSocket v1.1 or above.
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    NOTREACHED();
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             false /* private_api */,
179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             NULL,
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_frame_id_)) {
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bind_input_addr_ = net_addr;
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperTCPSocketMessageFilter::DoBind,
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
191a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
192a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     net_addr));
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& host,
199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    uint16_t port) {
200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // This is only supported by PPB_TCPSocket_Private.
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!IsPrivateAPI()) {
204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    NOTREACHED();
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_NOACCESS;
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
208a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SocketPermissionRequest request(
209a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      SocketPermissionRequest::TCP_CONNECT, host, port);
210a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             true /* private_api */,
212a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
213a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
214a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_frame_id_)) {
215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_NOACCESS;
216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RenderProcessHost* render_process_host =
219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      RenderProcessHost::FromID(render_process_id_);
220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!render_process_host)
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  BrowserContext* browser_context = render_process_host->GetBrowserContext();
223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!browser_context || !browser_context->GetResourceContext())
224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperTCPSocketMessageFilter::DoConnect,
229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     host,
232a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     port,
233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     browser_context->GetResourceContext()));
234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  content::SocketPermissionRequest request =
243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pepper_socket_utils::CreateSocketPermissionRequest(
244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          content::SocketPermissionRequest::TCP_CONNECT, net_addr);
245a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
246a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             IsPrivateAPI(),
247a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
248a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_frame_id_)) {
250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_NOACCESS;
251424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
252424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
253424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  BrowserThread::PostTask(
254a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      BrowserThread::IO,
255a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      FROM_HERE,
256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress,
257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 this,
258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 context->MakeReplyMessageContext(),
259a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 net_addr));
260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& server_name,
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    uint16_t server_port,
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::vector<std::vector<char> >& trusted_certs,
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::vector<std::vector<char> >& untrusted_certs) {
269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Allow to do SSL handshake only if currently the socket has been connected
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // and there isn't pending read or write.
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  net::IPEndPoint peer_address;
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_->GetPeerAddress(&peer_address) != net::OK)
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new net::TCPClientSocket(socket_.Pass(), peer_address)));
286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::ClientSocketFactory* factory =
287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      net::ClientSocketFactory::GetDefaultFactory();
288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::HostPortPair host_port_pair(server_name, server_port);
289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::SSLClientSocketContext ssl_context;
290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ssl_context.transport_security_state =
292424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      ssl_context_helper_->GetTransportSecurityState();
293a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ssl_socket_ =
294a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      factory->CreateSSLClientSocket(handle.Pass(),
295a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     host_port_pair,
296a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     ssl_context_helper_->ssl_config(),
297a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     ssl_context);
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!ssl_socket_) {
299424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    LOG(WARNING) << "Failed to create an SSL client socket.";
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
301424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const ppapi::host::ReplyMessageContext reply_context(
307424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      context->MakeReplyMessageContext());
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = ssl_socket_->Connect(
309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
310a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 base::Unretained(this),
311a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 reply_context));
312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnSSLHandshakeCompleted(reply_context, net_result);
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgRead(
318424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t bytes_to_read) {
320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected() || end_of_file_reached_)
322424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (read_buffer_.get())
324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
325424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (bytes_to_read <= 0 ||
326424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
327424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
328424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
329424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
330424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(
331424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      context->MakeReplyMessageContext());
332424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  read_buffer_ = new net::IOBuffer(bytes_to_read);
33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = net::ERR_FAILED;
33568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_) {
33668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
337a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    net_result =
338a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        socket_->Read(read_buffer_.get(),
339a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                      bytes_to_read,
340a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                      base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
341a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                 base::Unretained(this),
342a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                 reply_context));
34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (ssl_socket_) {
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = ssl_socket_->Read(
34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        read_buffer_.get(),
34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        bytes_to_read,
34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
349a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
350a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   reply_context));
35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
352424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
353424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnReadCompleted(reply_context, net_result);
354424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
355424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
356424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
357424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
358424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
359424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& data) {
360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
361424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
36268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected())
363424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (write_buffer_base_.get() || write_buffer_.get())
365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  size_t data_size = data.size();
368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (data_size == 0 ||
369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
373424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_base_ = new net::IOBuffer(data_size);
374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memcpy(write_buffer_base_->data(), data.data(), data_size);
375424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_ =
376424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
377424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DoWrite(context->MakeReplyMessageContext());
378424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
379424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
380424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgListen(
38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t backlog) {
384effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // This is only supported by PPB_TCPSocket v1.1 or above.
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
38868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    NOTREACHED();
38968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  content::SocketPermissionRequest request =
39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pepper_socket_utils::CreateSocketPermissionRequest(
39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
395a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
396a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             false /* private_api */,
397a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
398a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
399a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_frame_id_)) {
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
403a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
404a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
405a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperTCPSocketMessageFilter::DoListen,
406a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
407a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
408a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     backlog));
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
41168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::HostMessageContext* context) {
414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pending_accept_)
41768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
41868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.state() != TCPSocketState::LISTENING)
41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pending_accept_ = true;
42268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      context->MakeReplyMessageContext());
42468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = socket_->Accept(
42568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &accepted_socket_,
42668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &accepted_address_,
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
428a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 base::Unretained(this),
429a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 reply_context));
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    OnAcceptCompleted(reply_context, net_result);
43268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
43368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
43468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgClose(
436424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context) {
437effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.state() == TCPSocketState::CLOSED)
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_OK;
44068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
44168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.DoTransition(TCPSocketState::CLOSE, true);
44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_) {
44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_->Close();
44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (ssl_socket_) {
44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ssl_socket_->Disconnect();
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK;
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_TCPSocket_Option name,
454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::SocketOptionData& value) {
455effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (name) {
458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PP_TCPSOCKET_OPTION_NO_DELAY: {
45968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (state_.state() != TCPSocketState::CONNECTED)
46068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return PP_ERROR_FAILED;
46168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      bool boolean_value = false;
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (!value.GetBool(&boolean_value))
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        return PP_ERROR_BADARGUMENT;
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
467424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
468424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
46968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (state_.state() != TCPSocketState::CONNECTED)
47068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return PP_ERROR_FAILED;
47168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
472424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      int32_t integer_value = 0;
473424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (!value.GetInt32(&integer_value) || integer_value <= 0)
474424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        return PP_ERROR_BADARGUMENT;
475424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
476c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      int net_result = net::ERR_UNEXPECTED;
477424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
478424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
479424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          return PP_ERROR_BADARGUMENT;
480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        net_result = socket_->SetSendBufferSize(integer_value);
481424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      } else {
482424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
483424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          return PP_ERROR_BADARGUMENT;
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        net_result = socket_->SetReceiveBufferSize(integer_value);
485424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // TODO(wtc): Add error mapping code.
487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED;
488424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    default: {
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      NOTREACHED();
491424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return PP_ERROR_BADARGUMENT;
492424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
493424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
49668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoBind(
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
499effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
50068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::BIND)) {
50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendBindError(context, PP_ERROR_INPROGRESS);
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
50468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
50568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::BIND)) {
50668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendBindError(context, PP_ERROR_FAILED);
50768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
50868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
51068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int pp_result = PP_OK;
51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  do {
51268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net::IPAddressNumber address;
51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int port;
514a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
515a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            net_addr, &address, &port)) {
51668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pp_result = PP_ERROR_ADDRESS_INVALID;
51768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
51868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
51968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net::IPEndPoint bind_addr(address, port);
52068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(!socket_->IsValid());
52268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
52468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
52768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
52868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
53268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
53368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
53468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net::IPEndPoint ip_end_point_local;
535a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    pp_result =
536a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
53768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
53868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
53968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PP_NetAddress_Private local_addr =
54168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        NetAddressPrivateImpl::kInvalidNetAddress;
54268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
54368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            ip_end_point_local.address(),
54468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            ip_end_point_local.port(),
54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            &local_addr)) {
54668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pp_result = PP_ERROR_ADDRESS_INVALID;
54768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
54868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
54968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
55068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendBindReply(context, PP_OK, local_addr);
55168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.DoTransition(TCPSocketState::BIND, true);
55268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
55368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } while (false);
55468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_->IsValid())
55568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_->Close();
55668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendBindError(context, pp_result);
55768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.DoTransition(TCPSocketState::BIND, false);
558424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
559424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
560424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoConnect(
561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
562424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& host,
563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    uint16_t port,
564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ResourceContext* resource_context) {
565effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
56768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
569424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
570424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
571424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
57268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::CONNECT);
5731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  address_index_ = 0;
5741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  address_list_.clear();
575424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
576a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  resolver_.reset(
577a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new net::SingleRequestHostResolver(resource_context->GetHostResolver()));
578424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int net_result = resolver_->Resolve(
579424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      request_info,
580424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      net::DEFAULT_PRIORITY,
581424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      &address_list_,
582424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
583a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 base::Unretained(this),
584a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 context),
585424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      net::BoundNetLog());
586424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
587424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnResolveCompleted(context, net_result);
588424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
589424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
590424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
591424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
592424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
593effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
594424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
59568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
596424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
597424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
598424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
599424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
60068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::CONNECT);
60168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
602424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::IPAddressNumber address;
603424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int port;
604a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
605a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          net_addr, &address, &port)) {
60668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
607424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
608424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
609424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
610424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
611424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Copy the single IPEndPoint to address_list_.
6121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  address_index_ = 0;
613424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  address_list_.clear();
614424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  address_list_.push_back(net::IPEndPoint(address, port));
615424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartConnect(context);
616424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
617424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
618424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoWrite(
619424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context) {
620effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
621424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_base_.get());
622424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_.get());
623424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK_GT(write_buffer_->BytesRemaining(), 0);
62468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(state_.IsConnected());
62568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
62668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = net::ERR_FAILED;
62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_) {
62868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
62968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = socket_->Write(
63068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_.get(),
63168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_->BytesRemaining(),
63268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
633a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
634a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   context));
63568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (ssl_socket_) {
63668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
63768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = ssl_socket_->Write(
63868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_.get(),
63968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_->BytesRemaining(),
64068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
641a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
642a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   context));
64368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
644424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
645424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnWriteCompleted(context, net_result);
646424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
647424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
64868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoListen(
64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
65068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t backlog) {
651effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
65268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::LISTEN)) {
65468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendListenReply(context, PP_ERROR_INPROGRESS);
65568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendListenReply(context, PP_ERROR_FAILED);
65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
66168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
66268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
66368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendListenReply(context, pp_result);
66468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
66568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
66668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
667424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnResolveCompleted(
668424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
669424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
670effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
671424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
67268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::CONNECT)) {
67368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(state_.state() == TCPSocketState::CLOSED);
674424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
675424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
676424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
677424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
678424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::OK) {
679424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, NetErrorToPepperError(net_result));
68068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
681424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
682424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
683424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
684424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartConnect(context);
685424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
686424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
687424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::StartConnect(
688424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context) {
689effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
69068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(state_.IsPending(TCPSocketState::CONNECT));
6911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_LT(address_index_, address_list_.size());
692424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
69368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = net::OK;
69468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!socket_->IsValid())
6951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    net_result = socket_->Open(address_list_[address_index_].GetFamily());
696424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
69768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (net_result == net::OK) {
69868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = socket_->Connect(
6991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        address_list_[address_index_],
70068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
701a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
702a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   context));
70368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
704424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
705424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnConnectCompleted(context, net_result);
706424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
707424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
708424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnConnectCompleted(
709424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
710424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
711effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
712424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
71368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::CONNECT)) {
71468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(state_.state() == TCPSocketState::CLOSED);
715424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
716424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
717424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
718424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
719424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int32_t pp_result = NetErrorToPepperError(net_result);
720424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  do {
721424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (pp_result != PP_OK)
722424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
723424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
724424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::IPEndPoint ip_end_point_local;
725424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::IPEndPoint ip_end_point_remote;
726a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    pp_result =
727a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
728424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (pp_result != PP_OK)
729424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
730a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    pp_result =
731a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        NetErrorToPepperError(socket_->GetPeerAddress(&ip_end_point_remote));
732424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (pp_result != PP_OK)
733424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
734424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
735424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_NetAddress_Private local_addr =
736424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        NetAddressPrivateImpl::kInvalidNetAddress;
737424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_NetAddress_Private remote_addr =
738424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        NetAddressPrivateImpl::kInvalidNetAddress;
739424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
740424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_local.address(),
741424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_local.port(),
742424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            &local_addr) ||
743424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        !NetAddressPrivateImpl::IPEndPointToNetAddress(
744424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_remote.address(),
745424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_remote.port(),
746424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            &remote_addr)) {
747424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pp_result = PP_ERROR_ADDRESS_INVALID;
748424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
749424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
750424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
75168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_->SetDefaultOptionsForClient();
752424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectReply(context, PP_OK, local_addr, remote_addr);
75368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(true);
754424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
755424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } while (false);
756424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
75768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
7581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DCHECK_EQ(1u, address_list_.size());
7591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    SendConnectError(context, pp_result);
76168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
76268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
76368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // We have to recreate |socket_| because it doesn't allow a second connect
76468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // attempt. We won't lose any state such as bound address or set options,
76568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // because in the private or v1.0 API, connect must be the first operation.
76668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
7671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (address_index_ + 1 < address_list_.size()) {
7691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
7701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      address_index_++;
7711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      StartConnect(context);
7721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
7731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      SendConnectError(context, pp_result);
7741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // In order to maintain backward compatibility, allow further attempts to
7751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // connect the socket.
7761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      state_ = TCPSocketState(TCPSocketState::INITIAL);
7771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
77868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
779424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
780424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
781424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
782424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
783424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
784effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
785424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
78668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
78768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(state_.state() == TCPSocketState::CLOSED);
788424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendSSLHandshakeReply(context, PP_ERROR_FAILED);
789424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
790424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
79168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
792424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
79368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.CompletePendingTransition(net_result == net::OK);
794424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
795424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
796424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnReadCompleted(
797424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
798424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
799effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
800424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(read_buffer_.get());
801424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
802424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result > 0) {
803a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SendReadReply(
804a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        context, PP_OK, std::string(read_buffer_->data(), net_result));
805424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } else if (net_result == 0) {
806424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    end_of_file_reached_ = true;
807424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendReadReply(context, PP_OK, std::string());
808424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } else {
809424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendReadError(context, NetErrorToPepperError(net_result));
810424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
811424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  read_buffer_ = NULL;
812424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
813424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
814424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnWriteCompleted(
815424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
816424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
817effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
818424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_base_.get());
819424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_.get());
820424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
821424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Note: For partial writes of 0 bytes, don't continue writing to avoid a
822424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // likely infinite loop.
823424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result > 0) {
824424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    write_buffer_->DidConsume(net_result);
82568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
826424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DoWrite(context);
827424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return;
828424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
829424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
830424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
831424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result >= 0)
832424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendWriteReply(context, write_buffer_->BytesConsumed());
833424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  else
834424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendWriteReply(context, NetErrorToPepperError(net_result));
835424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
836424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_ = NULL;
837424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_base_ = NULL;
838424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
839424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
84068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnAcceptCompleted(
84168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
84268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int net_result) {
843effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
84468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(pending_accept_);
84568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
84668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pending_accept_ = false;
84768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
84868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (net_result != net::OK) {
84968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, NetErrorToPepperError(net_result));
85068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
85168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
85268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
85368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(accepted_socket_.get());
85468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
85568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  net::IPEndPoint ip_end_point_local;
85668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
85768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
85868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
859a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int32_t pp_result = NetErrorToPepperError(
860a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      accepted_socket_->GetLocalAddress(&ip_end_point_local));
86168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pp_result != PP_OK) {
86268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, pp_result);
86368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
86468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
86568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
86668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          ip_end_point_local.address(),
86768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          ip_end_point_local.port(),
86868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          &local_addr) ||
86968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      !NetAddressPrivateImpl::IPEndPointToNetAddress(
87068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          accepted_address_.address(),
87168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          accepted_address_.port(),
87268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          &remote_addr)) {
87368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
87468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
87568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
87668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
87768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |factory_| is guaranteed to be non-NULL here. Only those instances created
87868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // in CONNECTED state have a NULL |factory_|, while getting here requires
87968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // LISTENING state.
88068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<ppapi::host::ResourceHost> host =
88168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      factory_->CreateAcceptedTCPSocket(
88268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          instance_, version_, accepted_socket_.Pass());
88368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!host) {
88468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, PP_ERROR_NOSPACE);
88568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
88668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
88768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
88868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pending_host_id)
88968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  else
89168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, PP_ERROR_NOSPACE);
89268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
89368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
89468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendBindReply(
89568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
89668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t pp_result,
89768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& local_addr) {
89868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
89968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  reply_context.params.set_result(pp_result);
90068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
90168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
90268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
90368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendBindError(
90468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
90568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t pp_error) {
90668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
90768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
90868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
909424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendConnectReply(
910424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
911424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_result,
912424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& local_addr,
913424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& remote_addr) {
914424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
915424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  reply_context.params.set_result(pp_result);
916424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendReply(reply_context,
917424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
918424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
919424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
920424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendConnectError(
921424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
922424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_error) {
923424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendConnectReply(context,
924424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   pp_error,
925424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   NetAddressPrivateImpl::kInvalidNetAddress,
926424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   NetAddressPrivateImpl::kInvalidNetAddress);
927424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
928424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
929424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
930424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
931424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_result) {
932424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
933424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  reply_context.params.set_result(pp_result);
934424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::PPB_X509Certificate_Fields certificate_fields;
935424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (pp_result == PP_OK) {
936424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Our socket is guaranteed to be an SSL socket if we get here.
937424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::SSLInfo ssl_info;
93868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ssl_socket_->GetSSLInfo(&ssl_info);
939424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (ssl_info.cert.get()) {
940424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
941424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                &certificate_fields);
942424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
943424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
944424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendReply(reply_context,
945424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
946424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
947424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
948424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendReadReply(
949424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
950424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_result,
951424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& data) {
952424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
953