17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// found in the LICENSE file.
47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/proxy/tcp_socket_resource_base.h"
67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <cstring>
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/bind.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/logging.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/c/pp_bool.h"
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/proxy/error_conversion.h"
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/shared_impl/socket_option_data.h"
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/shared_impl/var.h"
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ppapi/shared_impl/var_tracker.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/thunk/enter.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/thunk/ppb_x509_certificate_private_api.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace ppapi {
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace proxy {
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int32_t TCPSocketResourceBase::kMaxReadSize = 1024 * 1024;
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int32_t TCPSocketResourceBase::kMaxWriteSize = 1024 * 1024;
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int32_t TCPSocketResourceBase::kMaxSendBufferSize =
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    1024 * TCPSocketResourceBase::kMaxWriteSize;
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int32_t TCPSocketResourceBase::kMaxReceiveBufferSize =
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    1024 * TCPSocketResourceBase::kMaxReadSize;
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TCPSocketResourceBase::TCPSocketResourceBase(Connection connection,
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                             PP_Instance instance,
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                             TCPSocketVersion version)
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : PluginResource(connection, instance),
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_(TCPSocketState::INITIAL),
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      read_buffer_(NULL),
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      bytes_to_read_(-1),
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      accepted_tcp_socket_(NULL),
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      version_(version) {
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  local_addr_.size = 0;
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memset(local_addr_.data, 0,
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)         arraysize(local_addr_.data) * sizeof(*local_addr_.data));
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  remote_addr_.size = 0;
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memset(remote_addr_.data, 0,
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)         arraysize(remote_addr_.data) * sizeof(*remote_addr_.data));
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TCPSocketResourceBase::TCPSocketResourceBase(
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    Connection connection,
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    PP_Instance instance,
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    TCPSocketVersion version,
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const PP_NetAddress_Private& local_addr,
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& remote_addr)
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : PluginResource(connection, instance),
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_(TCPSocketState::CONNECTED),
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      read_buffer_(NULL),
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      bytes_to_read_(-1),
60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      local_addr_(local_addr),
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      remote_addr_(remote_addr),
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      accepted_tcp_socket_(NULL),
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      version_(version) {
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TCPSocketResourceBase::~TCPSocketResourceBase() {
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CloseImpl();
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t TCPSocketResourceBase::BindImpl(
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private* addr,
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!addr)
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::BIND))
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::BIND))
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bind_callback_ = callback;
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::BIND);
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_BindReply>(
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      BROWSER,
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      PpapiHostMsg_TCPSocket_Bind(*addr),
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgBindReply,
87d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
88d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t TCPSocketResourceBase::ConnectImpl(
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const char* host,
94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    uint16_t port,
95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!host)
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::CONNECT))
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::CONNECT))
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_FAILED;
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  connect_callback_ = callback;
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::CONNECT);
105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_ConnectReply>(
107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      BROWSER,
108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      PpapiHostMsg_TCPSocket_Connect(host, port),
109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgConnectReply,
110d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
111d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t TCPSocketResourceBase::ConnectWithNetAddressImpl(
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const PP_NetAddress_Private* addr,
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!addr)
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::CONNECT))
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::CONNECT))
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_FAILED;
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  connect_callback_ = callback;
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::CONNECT);
127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_ConnectReply>(
129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      BROWSER,
130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      PpapiHostMsg_TCPSocket_ConnectWithNetAddress(*addr),
131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgConnectReply,
132d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
133d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PP_Bool TCPSocketResourceBase::GetLocalAddressImpl(
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_NetAddress_Private* local_addr) {
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsBound() || !local_addr)
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_FALSE;
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  *local_addr = local_addr_;
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_TRUE;
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PP_Bool TCPSocketResourceBase::GetRemoteAddressImpl(
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_NetAddress_Private* remote_addr) {
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected() || !remote_addr)
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_FALSE;
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  *remote_addr = remote_addr_;
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_TRUE;
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t TCPSocketResourceBase::SSLHandshakeImpl(
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const char* server_name,
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    uint16_t server_port,
1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!server_name)
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::SSL_CONNECT) ||
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      TrackedCallback::IsPending(read_callback_) ||
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      TrackedCallback::IsPending(write_callback_)) {
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT))
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ssl_handshake_callback_ = callback;
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_SSLHandshakeReply>(
172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      BROWSER,
173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      PpapiHostMsg_TCPSocket_SSLHandshake(server_name,
174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                          server_port,
175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                          trusted_certificates_,
176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                          untrusted_certificates_),
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgSSLHandshakeReply,
178d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
179d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PP_Resource TCPSocketResourceBase::GetServerCertificateImpl() {
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!server_certificate_.get())
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return 0;
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return server_certificate_->GetReference();
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PP_Bool TCPSocketResourceBase::AddChainBuildingCertificateImpl(
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_Resource certificate,
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_Bool trusted) {
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // TODO(raymes): The plumbing for this functionality is implemented but the
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // certificates aren't yet used for the connection, so just return false for
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // now.
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_FALSE;
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  thunk::EnterResourceNoLock<thunk::PPB_X509Certificate_Private_API>
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  enter_cert(certificate, true);
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (enter_cert.failed())
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_FALSE;
2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PP_Var der_var = enter_cert.object()->GetField(
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      PP_X509CERTIFICATE_PRIVATE_RAW);
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ArrayBufferVar* der_array_buffer = ArrayBufferVar::FromPPVar(der_var);
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PP_Bool success = PP_FALSE;
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (der_array_buffer) {
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const char* der_bytes = static_cast<const char*>(der_array_buffer->Map());
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    uint32_t der_length = der_array_buffer->ByteLength();
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::vector<char> der(der_bytes, der_bytes + der_length);
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (PP_ToBool(trusted))
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      trusted_certificates_.push_back(der);
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    else
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      untrusted_certificates_.push_back(der);
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    success = PP_TRUE;
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(der_var);
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return success;
2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t TCPSocketResourceBase::ReadImpl(
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    char* buffer,
222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t bytes_to_read,
223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!buffer || bytes_to_read <= 0)
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected())
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_FAILED;
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (TrackedCallback::IsPending(read_callback_) ||
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_.IsPending(TCPSocketState::SSL_CONNECT))
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  read_buffer_ = buffer;
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize);
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  read_callback_ = callback;
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_ReadReply>(
237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      BROWSER,
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      PpapiHostMsg_TCPSocket_Read(bytes_to_read_),
239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgReadReply,
240d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
241d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
245424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t TCPSocketResourceBase::WriteImpl(
246424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const char* buffer,
247424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int32_t bytes_to_write,
248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!buffer || bytes_to_write <= 0)
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected())
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_FAILED;
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (TrackedCallback::IsPending(write_callback_) ||
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_.IsPending(TCPSocketState::SSL_CONNECT))
2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (bytes_to_write > kMaxWriteSize)
2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    bytes_to_write = kMaxWriteSize;
2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  write_callback_ = callback;
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_WriteReply>(
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      BROWSER,
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      PpapiHostMsg_TCPSocket_Write(std::string(buffer, bytes_to_write)),
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgWriteReply,
267d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
268d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t TCPSocketResourceBase::ListenImpl(
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int32_t backlog,
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (backlog <= 0)
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.IsPending(TCPSocketState::LISTEN))
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsValidTransition(TCPSocketState::LISTEN))
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  listen_callback_ = callback;
28368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.SetPendingTransition(TCPSocketState::LISTEN);
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_ListenReply>(
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      BROWSER,
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      PpapiHostMsg_TCPSocket_Listen(backlog),
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgListenReply,
289d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
290d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int32_t TCPSocketResourceBase::AcceptImpl(
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    PP_Resource* accepted_tcp_socket,
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!accepted_tcp_socket)
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_BADARGUMENT;
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (TrackedCallback::IsPending(accept_callback_))
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_INPROGRESS;
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.state() != TCPSocketState::LISTENING)
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return PP_ERROR_FAILED;
30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  accept_callback_ = callback;
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  accepted_tcp_socket_ = accepted_tcp_socket;
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_AcceptReply>(
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      BROWSER,
30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      PpapiHostMsg_TCPSocket_Accept(),
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgAcceptReply,
311d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
312d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TCPSocketResourceBase::CloseImpl() {
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.state() == TCPSocketState::CLOSED)
3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.DoTransition(TCPSocketState::CLOSE, true);
3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Post(BROWSER, PpapiHostMsg_TCPSocket_Close());
3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PostAbortIfNecessary(&bind_callback_);
3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PostAbortIfNecessary(&connect_callback_);
3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PostAbortIfNecessary(&ssl_handshake_callback_);
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PostAbortIfNecessary(&read_callback_);
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PostAbortIfNecessary(&write_callback_);
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PostAbortIfNecessary(&listen_callback_);
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  PostAbortIfNecessary(&accept_callback_);
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  read_buffer_ = NULL;
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bytes_to_read_ = -1;
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  server_certificate_ = NULL;
33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  accepted_tcp_socket_ = NULL;
3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int32_t TCPSocketResourceBase::SetOptionImpl(
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    PP_TCPSocket_Option name,
3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const PP_Var& value,
3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_refptr<TrackedCallback> callback) {
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SocketOptionData option_data;
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  switch (name) {
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PP_TCPSOCKET_OPTION_NO_DELAY: {
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!state_.IsConnected())
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return PP_ERROR_FAILED;
34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (value.type != PP_VARTYPE_BOOL)
3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return PP_ERROR_BADARGUMENT;
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      option_data.SetBool(PP_ToBool(value.value.as_bool));
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
35468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!state_.IsConnected())
35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return PP_ERROR_FAILED;
35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (value.type != PP_VARTYPE_INT32)
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        return PP_ERROR_BADARGUMENT;
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      option_data.SetInt32(value.value.as_int);
360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default: {
363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return PP_ERROR_BADARGUMENT;
365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  set_option_callbacks_.push(callback);
369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Call<PpapiPluginMsg_TCPSocket_SetOptionReply>(
371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      BROWSER,
372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      PpapiHostMsg_TCPSocket_SetOption(name, option_data),
373424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&TCPSocketResourceBase::OnPluginMsgSetOptionReply,
374d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)                 base::Unretained(this)),
375d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)      callback);
376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return PP_OK_COMPLETIONPENDING;
3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
379424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPSocketResourceBase::PostAbortIfNecessary(
380424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    scoped_refptr<TrackedCallback>* callback) {
381424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (TrackedCallback::IsPending(*callback))
382424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    (*callback)->PostAbort();
383424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
384424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgBindReply(
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ResourceMessageReplyParams& params,
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& local_addr) {
38868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // It is possible that CloseImpl() has been called. We don't want to update
38968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // class members in this case.
39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::BIND))
39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(TrackedCallback::IsPending(bind_callback_));
39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (params.result() == PP_OK) {
39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    local_addr_ = local_addr;
39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(true);
39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RunCallback(bind_callback_, params.result());
40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgConnectReply(
404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ResourceMessageReplyParams& params,
405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& local_addr,
406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const PP_NetAddress_Private& remote_addr) {
40768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // It is possible that CloseImpl() has been called. We don't want to update
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // class members in this case.
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::CONNECT))
410424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
411424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(TrackedCallback::IsPending(connect_callback_));
413424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (params.result() == PP_OK) {
414424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    local_addr_ = local_addr;
415424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    remote_addr_ = remote_addr;
41668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(true);
41768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
41868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (version_ == TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_.CompletePendingTransition(false);
42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else {
42168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // In order to maintain backward compatibility, allow to connect the
42268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // socket again.
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_ = TCPSocketState(TCPSocketState::INITIAL);
42468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
425424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RunCallback(connect_callback_, params.result());
427424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
428424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
429424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgSSLHandshakeReply(
430424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      const ResourceMessageReplyParams& params,
431424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      const PPB_X509Certificate_Fields& certificate_fields) {
43268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // It is possible that CloseImpl() has been called. We don't want to
43368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // update class members in this case.
43468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::SSL_CONNECT))
435424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
436424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
43768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(TrackedCallback::IsPending(ssl_handshake_callback_));
438424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (params.result() == PP_OK) {
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(true);
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    server_certificate_ = new PPB_X509Certificate_Private_Shared(
441424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        OBJECT_IS_PROXY,
442424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        pp_instance(),
443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        certificate_fields);
444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } else {
44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    state_.CompletePendingTransition(false);
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RunCallback(ssl_handshake_callback_, params.result());
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgReadReply(
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ResourceMessageReplyParams& params,
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& data) {
45368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // It is possible that CloseImpl() has been called. We shouldn't access the
45468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // buffer in that case. The user may have released it.
45568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected() || !TrackedCallback::IsPending(read_callback_) ||
45668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      !read_buffer_) {
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
45868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const bool succeeded = params.result() == PP_OK;
461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (succeeded) {
462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!data.empty())
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      memmove(read_buffer_, data.c_str(), data.size());
465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
4667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  read_buffer_ = NULL;
4677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bytes_to_read_ = -1;
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
46968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RunCallback(read_callback_,
47068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)              succeeded ? static_cast<int32_t>(data.size()) : params.result());
4717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
473424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgWriteReply(
474424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ResourceMessageReplyParams& params) {
47568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsConnected() || !TrackedCallback::IsPending(write_callback_))
476424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
477424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RunCallback(write_callback_, params.result());
4787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
48068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgListenReply(
48168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ResourceMessageReplyParams& params) {
48268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!state_.IsPending(TCPSocketState::LISTEN))
48368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
48468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
48568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK(TrackedCallback::IsPending(listen_callback_));
48668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  state_.CompletePendingTransition(params.result() == PP_OK);
48768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
48868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RunCallback(listen_callback_, params.result());
48968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
49068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
49168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgAcceptReply(
49268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ResourceMessageReplyParams& params,
49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int pending_host_id,
49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& local_addr,
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const PP_NetAddress_Private& remote_addr) {
49668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // It is possible that CloseImpl() has been called. We shouldn't access the
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // output parameter in that case. The user may have released it.
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (state_.state() != TCPSocketState::LISTENING ||
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      !TrackedCallback::IsPending(accept_callback_) || !accepted_tcp_socket_) {
50068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (params.result() == PP_OK) {
50468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    *accepted_tcp_socket_ = CreateAcceptedSocket(pending_host_id, local_addr,
50568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                 remote_addr);
50668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
50768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  accepted_tcp_socket_ = NULL;
50868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RunCallback(accept_callback_, params.result());
50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
51068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
511424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPSocketResourceBase::OnPluginMsgSetOptionReply(
512424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const ResourceMessageReplyParams& params) {
513424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (set_option_callbacks_.empty()) {
514424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    NOTREACHED();
515424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
516424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
517424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<TrackedCallback> callback = set_option_callbacks_.front();
518424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  set_option_callbacks_.pop();
519424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (TrackedCallback::IsPending(callback))
520424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    RunCallback(callback, params.result());
521424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
522424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
523424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void TCPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback,
524424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                        int32_t pp_result) {
52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  callback->Run(ConvertNetworkAPIErrorForCompatibility(
52668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pp_result, version_ == TCP_SOCKET_VERSION_PRIVATE));
5277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
5287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace ppapi
530424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace proxy
531