pepper_tcp_socket_message_filter.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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) {
143424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Connect,
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    OnMsgConnect)
147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      PpapiHostMsg_TCPSocket_ConnectWithNetAddress, OnMsgConnectWithNetAddress)
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SSLHandshake,
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    OnMsgSSLHandshake)
151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Read, OnMsgRead)
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Listen, OnMsgListen)
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Accept,
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      OnMsgAccept)
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Close, OnMsgClose)
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SetOption,
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    OnMsgSetOption)
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_ERROR_FAILED;
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgBind(
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // This is only supported by PPB_TCPSocket v1.1 or above.
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    NOTREACHED();
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             false /* private_api */,
176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             NULL,
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_frame_id_)) {
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bind_input_addr_ = net_addr;
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperTCPSocketMessageFilter::DoBind,
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     net_addr));
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& host,
196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    uint16_t port) {
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // This is only supported by PPB_TCPSocket_Private.
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!IsPrivateAPI()) {
201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    NOTREACHED();
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_NOACCESS;
203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SocketPermissionRequest request(
206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      SocketPermissionRequest::TCP_CONNECT, host, port);
207a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
208a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             true /* private_api */,
209a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
210a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_frame_id_)) {
212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_NOACCESS;
213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RenderProcessHost* render_process_host =
216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      RenderProcessHost::FromID(render_process_id_);
217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!render_process_host)
218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  BrowserContext* browser_context = render_process_host->GetBrowserContext();
220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!browser_context || !browser_context->GetResourceContext())
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
223a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
224a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
225a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperTCPSocketMessageFilter::DoConnect,
226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     host,
229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     port,
230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     browser_context->GetResourceContext()));
231424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  content::SocketPermissionRequest request =
240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pepper_socket_utils::CreateSocketPermissionRequest(
241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          content::SocketPermissionRequest::TCP_CONNECT, net_addr);
242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             IsPrivateAPI(),
244a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
245a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_frame_id_)) {
247424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_NOACCESS;
248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
249424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  BrowserThread::PostTask(
251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      BrowserThread::IO,
252a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      FROM_HERE,
253a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress,
254a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 this,
255a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 context->MakeReplyMessageContext(),
256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 net_addr));
257424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
258424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& server_name,
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    uint16_t server_port,
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::vector<std::vector<char> >& trusted_certs,
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::vector<std::vector<char> >& untrusted_certs) {
266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Allow to do SSL handshake only if currently the socket has been connected
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // and there isn't pending read or write.
27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  net::IPEndPoint peer_address;
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_->GetPeerAddress(&peer_address) != net::OK)
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new net::TCPClientSocket(socket_.Pass(), peer_address)));
283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::ClientSocketFactory* factory =
284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      net::ClientSocketFactory::GetDefaultFactory();
285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::HostPortPair host_port_pair(server_name, server_port);
286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::SSLClientSocketContext ssl_context;
287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ssl_context.transport_security_state =
289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      ssl_context_helper_->GetTransportSecurityState();
290a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ssl_socket_ =
291a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      factory->CreateSSLClientSocket(handle.Pass(),
292a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     host_port_pair,
293a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     ssl_context_helper_->ssl_config(),
294a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     ssl_context);
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!ssl_socket_) {
296424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    LOG(WARNING) << "Failed to create an SSL client socket.";
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
299424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const ppapi::host::ReplyMessageContext reply_context(
304424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      context->MakeReplyMessageContext());
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = ssl_socket_->Connect(
306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
307a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 base::Unretained(this),
308a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 reply_context));
309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnSSLHandshakeCompleted(reply_context, net_result);
311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgRead(
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t bytes_to_read) {
317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected() || end_of_file_reached_)
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
320424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (read_buffer_.get())
321424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
322424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (bytes_to_read <= 0 ||
323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
325424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
326424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
327424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(
328424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      context->MakeReplyMessageContext());
329424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  read_buffer_ = new net::IOBuffer(bytes_to_read);
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = net::ERR_FAILED;
33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_) {
33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
334a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    net_result =
335a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        socket_->Read(read_buffer_.get(),
336a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                      bytes_to_read,
337a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                      base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
338a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                 base::Unretained(this),
339a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                 reply_context));
34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (ssl_socket_) {
34168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = ssl_socket_->Read(
34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        read_buffer_.get(),
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        bytes_to_read,
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
346a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   reply_context));
34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
349424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
350424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnReadCompleted(reply_context, net_result);
351424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
352424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
353424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
354424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
355424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
356424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& data) {
357effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
358424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected())
360424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_FAILED;
361424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (write_buffer_base_.get() || write_buffer_.get())
362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
363424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  size_t data_size = data.size();
365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (data_size == 0 ||
366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_base_ = new net::IOBuffer(data_size);
371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memcpy(write_buffer_base_->data(), data.data(), data_size);
372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_ =
373424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DoWrite(context->MakeReplyMessageContext());
375424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
376424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
377424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
37868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgListen(
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t backlog) {
381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // This is only supported by PPB_TCPSocket v1.1 or above.
38468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    NOTREACHED();
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
38868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
38968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  content::SocketPermissionRequest request =
39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pepper_socket_utils::CreateSocketPermissionRequest(
39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
392a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
393a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             false /* private_api */,
394a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             &request,
395a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_process_id_,
396a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                             render_frame_id_)) {
39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_NOACCESS;
39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
400a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(BrowserThread::IO,
401a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          FROM_HERE,
402a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                          base::Bind(&PepperTCPSocketMessageFilter::DoListen,
403a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     this,
404a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     context->MakeReplyMessageContext(),
405a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                     backlog));
40668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
40768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::HostMessageContext* context) {
411effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pending_accept_)
41468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.state() != TCPSocketState::LISTENING)
41668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
41768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
41868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pending_accept_ = true;
41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(
42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      context->MakeReplyMessageContext());
42168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = socket_->Accept(
42268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &accepted_socket_,
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &accepted_address_,
42468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
425a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 base::Unretained(this),
426a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 reply_context));
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
42868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    OnAcceptCompleted(reply_context, net_result);
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgClose(
433424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context) {
434effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.state() == TCPSocketState::CLOSED)
43668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_OK;
43768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.DoTransition(TCPSocketState::CLOSE, true);
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
44068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_) {
44168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_->Close();
44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (ssl_socket_) {
44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ssl_socket_->Disconnect();
44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return PP_OK;
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::HostMessageContext* context,
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_TCPSocket_Option name,
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::SocketOptionData& value) {
452effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (name) {
455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PP_TCPSOCKET_OPTION_NO_DELAY: {
45668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (state_.state() != TCPSocketState::CONNECTED)
45768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return PP_ERROR_FAILED;
45868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      bool boolean_value = false;
460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (!value.GetBool(&boolean_value))
461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        return PP_ERROR_BADARGUMENT;
46268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
46668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (state_.state() != TCPSocketState::CONNECTED)
46768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return PP_ERROR_FAILED;
46868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
469424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      int32_t integer_value = 0;
470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (!value.GetInt32(&integer_value) || integer_value <= 0)
471424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        return PP_ERROR_BADARGUMENT;
472424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
473c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      int net_result = net::ERR_UNEXPECTED;
474424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
475424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
476424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          return PP_ERROR_BADARGUMENT;
477c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        net_result = socket_->SetSendBufferSize(integer_value);
478424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      } else {
479424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
480424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          return PP_ERROR_BADARGUMENT;
481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        net_result = socket_->SetReceiveBufferSize(integer_value);
482424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // TODO(wtc): Add error mapping code.
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED;
485424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
486424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    default: {
487424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      NOTREACHED();
488424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return PP_ERROR_BADARGUMENT;
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
49168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
49268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoBind(
49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
496effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::BIND)) {
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendBindError(context, PP_ERROR_INPROGRESS);
50068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::BIND)) {
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendBindError(context, PP_ERROR_FAILED);
50468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
50568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
50668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
50768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int pp_result = PP_OK;
50868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  do {
50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net::IPAddressNumber address;
51068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int port;
511a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
512a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            net_addr, &address, &port)) {
51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pp_result = PP_ERROR_ADDRESS_INVALID;
51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
51668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net::IPEndPoint bind_addr(address, port);
51768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
51868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(!socket_->IsValid());
51968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
52068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
52168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
52268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
52468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
52668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
52868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net::IPEndPoint ip_end_point_local;
532a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    pp_result =
533a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
53468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (pp_result != PP_OK)
53568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
53668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
53768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PP_NetAddress_Private local_addr =
53868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        NetAddressPrivateImpl::kInvalidNetAddress;
53968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            ip_end_point_local.address(),
54168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            ip_end_point_local.port(),
54268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            &local_addr)) {
54368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pp_result = PP_ERROR_ADDRESS_INVALID;
54468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
54668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
54768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendBindReply(context, PP_OK, local_addr);
54868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.DoTransition(TCPSocketState::BIND, true);
54968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
55068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } while (false);
55168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_->IsValid())
55268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_->Close();
55368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendBindError(context, pp_result);
55468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.DoTransition(TCPSocketState::BIND, false);
555424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
556424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
557424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoConnect(
558424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
559424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& host,
560424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    uint16_t port,
561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ResourceContext* resource_context) {
562effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
56468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
56968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::CONNECT);
5701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  address_index_ = 0;
5711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  address_list_.clear();
572424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
573a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  resolver_.reset(
574a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new net::SingleRequestHostResolver(resource_context->GetHostResolver()));
575424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int net_result = resolver_->Resolve(
576424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      request_info,
577424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      net::DEFAULT_PRIORITY,
578424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      &address_list_,
579424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
580a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 base::Unretained(this),
581a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 context),
582424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      net::BoundNetLog());
583424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
584424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnResolveCompleted(context, net_result);
585424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
586424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
587424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
588424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
589424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& net_addr) {
590effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
591424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
59268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
593424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
594424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
595424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
596424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
59768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::CONNECT);
59868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
599424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  net::IPAddressNumber address;
600424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int port;
601a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
602a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          net_addr, &address, &port)) {
60368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
604424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
605424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
606424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
607424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
608424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Copy the single IPEndPoint to address_list_.
6091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  address_index_ = 0;
610424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  address_list_.clear();
611424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  address_list_.push_back(net::IPEndPoint(address, port));
612424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartConnect(context);
613424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
614424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
615424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoWrite(
616424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context) {
617effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
618424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_base_.get());
619424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_.get());
620424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK_GT(write_buffer_->BytesRemaining(), 0);
62168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(state_.IsConnected());
62268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
62368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = net::ERR_FAILED;
62468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (socket_) {
62568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
62668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = socket_->Write(
62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_.get(),
62868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_->BytesRemaining(),
62968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
630a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
631a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   context));
63268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (ssl_socket_) {
63368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
63468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = ssl_socket_->Write(
63568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_.get(),
63668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        write_buffer_->BytesRemaining(),
63768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
638a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
639a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   context));
64068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
641424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
642424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnWriteCompleted(context, net_result);
643424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
644424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
64568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::DoListen(
64668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
64768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t backlog) {
648effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
65068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::LISTEN)) {
65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendListenReply(context, PP_ERROR_INPROGRESS);
65268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
65468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
65568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendListenReply(context, PP_ERROR_FAILED);
65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendListenReply(context, pp_result);
66168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
66268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
66368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
664424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnResolveCompleted(
665424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
666424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
667effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
668424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
66968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::CONNECT)) {
67068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(state_.state() == TCPSocketState::CLOSED);
671424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
672424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
673424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
674424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
675424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::OK) {
676424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, NetErrorToPepperError(net_result));
67768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
678424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
679424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
680424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
681424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartConnect(context);
682424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
683424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
684424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::StartConnect(
685424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context) {
686effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
68768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(state_.IsPending(TCPSocketState::CONNECT));
6881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_LT(address_index_, address_list_.size());
689424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
69068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int net_result = net::OK;
69168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!socket_->IsValid())
6921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    net_result = socket_->Open(address_list_[address_index_].GetFamily());
693424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
69468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (net_result == net::OK) {
69568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    net_result = socket_->Connect(
6961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        address_list_[address_index_],
69768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
698a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   base::Unretained(this),
699a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   context));
70068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
701424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result != net::ERR_IO_PENDING)
702424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    OnConnectCompleted(context, net_result);
703424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
704424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
705424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnConnectCompleted(
706424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
707424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
708effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
709424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
71068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::CONNECT)) {
71168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(state_.state() == TCPSocketState::CLOSED);
712424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectError(context, PP_ERROR_FAILED);
713424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
714424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
715424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
716424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int32_t pp_result = NetErrorToPepperError(net_result);
717424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  do {
718424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (pp_result != PP_OK)
719424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
720424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
721424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::IPEndPoint ip_end_point_local;
722424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::IPEndPoint ip_end_point_remote;
723a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    pp_result =
724a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
725424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (pp_result != PP_OK)
726424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
727a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    pp_result =
728a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        NetErrorToPepperError(socket_->GetPeerAddress(&ip_end_point_remote));
729424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (pp_result != PP_OK)
730424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
731424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
732424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_NetAddress_Private local_addr =
733424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        NetAddressPrivateImpl::kInvalidNetAddress;
734424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_NetAddress_Private remote_addr =
735424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        NetAddressPrivateImpl::kInvalidNetAddress;
736424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
737424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_local.address(),
738424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_local.port(),
739424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            &local_addr) ||
740424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        !NetAddressPrivateImpl::IPEndPointToNetAddress(
741424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_remote.address(),
742424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            ip_end_point_remote.port(),
743424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            &remote_addr)) {
744424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pp_result = PP_ERROR_ADDRESS_INVALID;
745424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
746424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
747424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
74868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_->SetDefaultOptionsForClient();
749424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendConnectReply(context, PP_OK, local_addr, remote_addr);
75068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(true);
751424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
752424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } while (false);
753424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
75468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
7551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DCHECK_EQ(1u, address_list_.size());
7561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    SendConnectError(context, pp_result);
75868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
75968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
76068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // We have to recreate |socket_| because it doesn't allow a second connect
76168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // attempt. We won't lose any state such as bound address or set options,
76268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // because in the private or v1.0 API, connect must be the first operation.
76368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
7641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (address_index_ + 1 < address_list_.size()) {
7661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
7671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      address_index_++;
7681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      StartConnect(context);
7691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
7701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      SendConnectError(context, pp_result);
7711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // In order to maintain backward compatibility, allow further attempts to
7721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // connect the socket.
7731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      state_ = TCPSocketState(TCPSocketState::INITIAL);
7741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
77568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
776424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
777424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
778424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
779424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
780424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
781effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
782424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
78368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
78468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(state_.state() == TCPSocketState::CLOSED);
785424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendSSLHandshakeReply(context, PP_ERROR_FAILED);
786424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
787424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
78868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
789424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
79068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.CompletePendingTransition(net_result == net::OK);
791424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
792424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
793424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnReadCompleted(
794424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
795424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
796effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
797424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(read_buffer_.get());
798424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
799424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result > 0) {
800a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    SendReadReply(
801a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        context, PP_OK, std::string(read_buffer_->data(), net_result));
802424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } else if (net_result == 0) {
803424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    end_of_file_reached_ = true;
804424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendReadReply(context, PP_OK, std::string());
805424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } else {
806424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendReadError(context, NetErrorToPepperError(net_result));
807424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
808424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  read_buffer_ = NULL;
809424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
810424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
811424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnWriteCompleted(
812424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
813424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int net_result) {
814effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
815424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_base_.get());
816424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(write_buffer_.get());
817424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
818424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Note: For partial writes of 0 bytes, don't continue writing to avoid a
819424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // likely infinite loop.
820424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result > 0) {
821424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    write_buffer_->DidConsume(net_result);
82268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
823424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DoWrite(context);
824424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return;
825424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
826424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
827424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
828424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (net_result >= 0)
829424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendWriteReply(context, write_buffer_->BytesConsumed());
830424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  else
831424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SendWriteReply(context, NetErrorToPepperError(net_result));
832424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
833424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_ = NULL;
834424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  write_buffer_base_ = NULL;
835424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
836424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
83768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::OnAcceptCompleted(
83868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
83968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int net_result) {
840effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
84168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(pending_accept_);
84268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
84368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pending_accept_ = false;
84468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
84568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (net_result != net::OK) {
84668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, NetErrorToPepperError(net_result));
84768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
84868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
84968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
85068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(accepted_socket_.get());
85168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
85268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  net::IPEndPoint ip_end_point_local;
85368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
85468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
85568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
856a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int32_t pp_result = NetErrorToPepperError(
857a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      accepted_socket_->GetLocalAddress(&ip_end_point_local));
85868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pp_result != PP_OK) {
85968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, pp_result);
86068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
86168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
86268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
86368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          ip_end_point_local.address(),
86468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          ip_end_point_local.port(),
86568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          &local_addr) ||
86668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      !NetAddressPrivateImpl::IPEndPointToNetAddress(
86768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          accepted_address_.address(),
86868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          accepted_address_.port(),
86968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          &remote_addr)) {
87068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
87168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
87268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
87368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
87468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |factory_| is guaranteed to be non-NULL here. Only those instances created
87568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // in CONNECTED state have a NULL |factory_|, while getting here requires
87668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // LISTENING state.
87768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<ppapi::host::ResourceHost> host =
87868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      factory_->CreateAcceptedTCPSocket(
87968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          instance_, version_, accepted_socket_.Pass());
88068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!host) {
88168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, PP_ERROR_NOSPACE);
88268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
88368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
88468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
88568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pending_host_id)
88668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
88768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  else
88868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    SendAcceptError(context, PP_ERROR_NOSPACE);
88968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
89168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendBindReply(
89268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
89368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t pp_result,
89468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& local_addr) {
89568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
89668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  reply_context.params.set_result(pp_result);
89768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
89868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
89968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
90068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendBindError(
90168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
90268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t pp_error) {
90368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
90468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
90568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
906424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendConnectReply(
907424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
908424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_result,
909424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& local_addr,
910424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& remote_addr) {
911424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
912424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  reply_context.params.set_result(pp_result);
913424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendReply(reply_context,
914424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
915424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
916424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
917424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendConnectError(
918424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
919424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_error) {
920424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendConnectReply(context,
921424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   pp_error,
922424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   NetAddressPrivateImpl::kInvalidNetAddress,
923424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   NetAddressPrivateImpl::kInvalidNetAddress);
924424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
925424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
926424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
927424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
928424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_result) {
929424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
930424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  reply_context.params.set_result(pp_result);
931424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::PPB_X509Certificate_Fields certificate_fields;
932424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (pp_result == PP_OK) {
933424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Our socket is guaranteed to be an SSL socket if we get here.
934424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::SSLInfo ssl_info;
93568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ssl_socket_->GetSSLInfo(&ssl_info);
936424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (ssl_info.cert.get()) {
937424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
938424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                                &certificate_fields);
939424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
940424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
941424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendReply(reply_context,
942424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
943424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
944424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
945424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendReadReply(
946424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
947424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_result,
948424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& data) {
949424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
950424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  reply_context.params.set_result(pp_result);
951424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
952424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
953424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
954424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendReadError(
955424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
956424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_error) {
957424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendReadReply(context, pp_error, std::string());
958424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
959424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
960424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendWriteReply(
961424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
962424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t pp_result) {
963424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
964424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  reply_context.params.set_result(pp_result);
965424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
966424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
967424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
96868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendListenReply(
96968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
97068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t pp_result) {
97168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
97268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  reply_context.params.set_result(pp_result);
97368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
974424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
975424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
97668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendAcceptReply(
97768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
97868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t pp_result,
97968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int pending_host_id,
98068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& local_addr,
98168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& remote_addr) {
98268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ppapi::host::ReplyMessageContext reply_context(context);
98368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  reply_context.params.set_result(pp_result);
98468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SendReply(reply_context,
98568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            PpapiPluginMsg_TCPSocket_AcceptReply(
98668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                pending_host_id, local_addr, remote_addr));
987424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
988424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
98968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void PepperTCPSocketMessageFilter::SendAcceptError(
99068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ppapi::host::ReplyMessageContext& context,
99168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t pp_error) {
992a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SendAcceptReply(context,
993a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                  pp_error,
994a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                  0,
99568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                  NetAddressPrivateImpl::kInvalidNetAddress,
99668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                  NetAddressPrivateImpl::kInvalidNetAddress);
997424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
998424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
999424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace content
1000