summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/api/dev/ppb_tcp_socket_dev.idl115
-rw-r--r--ppapi/c/dev/ppb_tcp_socket_dev.h136
-rw-r--r--ppapi/cpp/dev/tcp_socket_dev.cc117
-rw-r--r--ppapi/cpp/dev/tcp_socket_dev.h53
-rw-r--r--ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c70
-rw-r--r--ppapi/ppapi_proxy.gypi2
-rw-r--r--ppapi/ppapi_shared.gypi4
-rw-r--r--ppapi/ppapi_sources.gypi5
-rw-r--r--ppapi/proxy/interface_list.cc2
-rw-r--r--ppapi/proxy/ppb_tcp_socket_private_proxy.h2
-rw-r--r--ppapi/proxy/ppb_tcp_socket_proxy.cc303
-rw-r--r--ppapi/proxy/ppb_tcp_socket_proxy.h58
-rw-r--r--ppapi/proxy/resource_creation_proxy.cc13
-rw-r--r--ppapi/proxy/resource_creation_proxy.h4
-rw-r--r--ppapi/shared_impl/api_id.h1
-rw-r--r--ppapi/shared_impl/private/tcp_socket_private_impl.cc288
-rw-r--r--ppapi/shared_impl/private/tcp_socket_private_impl.h87
-rw-r--r--ppapi/shared_impl/resource.h1
-rw-r--r--ppapi/shared_impl/tcp_socket_shared.cc339
-rw-r--r--ppapi/shared_impl/tcp_socket_shared.h133
-rw-r--r--ppapi/tests/all_c_includes.h1
-rw-r--r--ppapi/tests/all_cpp_includes.h1
-rw-r--r--ppapi/tests/test_tcp_socket.cc160
-rw-r--r--ppapi/tests/test_tcp_socket.h37
-rw-r--r--ppapi/tests/test_utils.cc81
-rw-r--r--ppapi/tests/test_utils.h11
-rw-r--r--ppapi/thunk/interfaces_ppb_public_dev.h4
-rw-r--r--ppapi/thunk/ppb_tcp_socket_api.h41
-rw-r--r--ppapi/thunk/ppb_tcp_socket_dev_thunk.cc128
-rw-r--r--ppapi/thunk/resource_creation_api.h5
30 files changed, 1848 insertions, 354 deletions
diff --git a/ppapi/api/dev/ppb_tcp_socket_dev.idl b/ppapi/api/dev/ppb_tcp_socket_dev.idl
new file mode 100644
index 0000000..dfc038a
--- /dev/null
+++ b/ppapi/api/dev/ppb_tcp_socket_dev.idl
@@ -0,0 +1,115 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * This file defines the <code>PPB_TCPSocket_Dev</code> interface.
+ */
+
+[generate_thunk]
+
+label Chrome {
+ M29 = 0.1
+};
+
+[assert_size(4)]
+enum PP_TCPSocket_Option_Dev {
+ // Disables coalescing of small writes to make TCP segments, and instead
+ // deliver data immediately. Value type is PP_VARTYPE_BOOL.
+ PP_TCPSOCKET_OPTION_NO_DELAY = 0,
+
+ // Specifies the socket send buffer in bytes. Value's type should be
+ // PP_VARTYPE_INT32.
+ // Note: This is only treated as a hint for the browser to set the buffer
+ // size. Even if SetOption() reports that this option has been successfully
+ // set, the browser doesn't guarantee to conform to it.
+ PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE = 1,
+
+ // Specifies the socket receive buffer in bytes. Value's type should be
+ // PP_VARTYPE_INT32.
+ // Note: This is only treated as a hint for the browser to set the buffer
+ // size. Even if SetOption() reports that this option has been successfully
+ // set, the browser doesn't guarantee to conform to it.
+ PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE = 2
+};
+
+/**
+ * The <code>PPB_TCPSocket_Dev</code> interface provides TCP socket operations.
+ */
+interface PPB_TCPSocket_Dev {
+ /**
+ * Allocates a TCP socket resource.
+ */
+ PP_Resource Create([in] PP_Instance instance);
+
+ /**
+ * Determines if a given resource is TCP socket.
+ */
+ PP_Bool IsTCPSocket([in] PP_Resource resource);
+
+ /**
+ * Connects to an address given by |addr|, which is a PPB_NetAddress_Dev
+ * resource.
+ */
+ int32_t Connect([in] PP_Resource tcp_socket,
+ [in] PP_Resource addr,
+ [in] PP_CompletionCallback callback);
+
+ /**
+ * Gets the local address of the socket, if it has been connected.
+ * Returns a PPB_NetAddress_Dev resource on success; returns 0 on failure.
+ */
+ PP_Resource GetLocalAddress([in] PP_Resource tcp_socket);
+
+ /**
+ * Gets the remote address of the socket, if it has been connected.
+ * Returns a PPB_NetAddress_Dev resource on success; returns 0 on failure.
+ */
+ PP_Resource GetRemoteAddress([in] PP_Resource tcp_socket);
+
+ /**
+ * Reads data from the socket. The size of |buffer| must be at least as large
+ * as |bytes_to_read|. May perform a partial read. Returns the number of bytes
+ * read or an error code. If the return value is 0, then it indicates that
+ * end-of-file was reached.
+ *
+ * Multiple outstanding read requests are not supported.
+ */
+ int32_t Read([in] PP_Resource tcp_socket,
+ [out] str_t buffer,
+ [in] int32_t bytes_to_read,
+ [in] PP_CompletionCallback callback);
+
+ /**
+ * Writes data to the socket. May perform a partial write. Returns the number
+ * of bytes written or an error code.
+ *
+ * Multiple outstanding write requests are not supported.
+ */
+ int32_t Write([in] PP_Resource tcp_socket,
+ [in] str_t buffer,
+ [in] int32_t bytes_to_write,
+ [in] PP_CompletionCallback callback);
+
+ /**
+ * Cancels any IO that may be pending, and disconnects the socket. Any pending
+ * callbacks will still run, reporting PP_ERROR_ABORTED if pending IO was
+ * interrupted. It is NOT valid to call Connect() again after a call to this
+ * method. Note: If the socket is destroyed when it is still connected, then
+ * it will be implicitly disconnected, so you are not required to call this
+ * method.
+ */
+ void Close([in] PP_Resource tcp_socket);
+
+ /**
+ * Sets an option on |tcp_socket|. Supported |name| and |value| parameters
+ * are as described for PP_TCPSocketOption_Dev. |callback| will be
+ * invoked with PP_OK if setting the option succeeds, or an error code
+ * otherwise. The socket must be connected before SetOption is called.
+ */
+ int32_t SetOption([in] PP_Resource tcp_socket,
+ [in] PP_TCPSocket_Option_Dev name,
+ [in] PP_Var value,
+ [in] PP_CompletionCallback callback);
+};
diff --git a/ppapi/c/dev/ppb_tcp_socket_dev.h b/ppapi/c/dev/ppb_tcp_socket_dev.h
new file mode 100644
index 0000000..d59bc31
--- /dev/null
+++ b/ppapi/c/dev/ppb_tcp_socket_dev.h
@@ -0,0 +1,136 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* From dev/ppb_tcp_socket_dev.idl modified Wed Jun 12 11:16:37 2013. */
+
+#ifndef PPAPI_C_DEV_PPB_TCP_SOCKET_DEV_H_
+#define PPAPI_C_DEV_PPB_TCP_SOCKET_DEV_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_macros.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+
+#define PPB_TCPSOCKET_DEV_INTERFACE_0_1 "PPB_TCPSocket(Dev);0.1"
+#define PPB_TCPSOCKET_DEV_INTERFACE PPB_TCPSOCKET_DEV_INTERFACE_0_1
+
+/**
+ * @file
+ * This file defines the <code>PPB_TCPSocket_Dev</code> interface.
+ */
+
+
+/**
+ * @addtogroup Enums
+ * @{
+ */
+typedef enum {
+ /* Disables coalescing of small writes to make TCP segments, and instead
+ * deliver data immediately. Value type is PP_VARTYPE_BOOL. */
+ PP_TCPSOCKET_OPTION_NO_DELAY = 0,
+ /* Specifies the socket send buffer in bytes. Value's type should be
+ * PP_VARTYPE_INT32.
+ * Note: This is only treated as a hint for the browser to set the buffer
+ * size. Even if SetOption() reports that this option has been successfully
+ * set, the browser doesn't guarantee to conform to it. */
+ PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE = 1,
+ /* Specifies the socket receive buffer in bytes. Value's type should be
+ * PP_VARTYPE_INT32.
+ * Note: This is only treated as a hint for the browser to set the buffer
+ * size. Even if SetOption() reports that this option has been successfully
+ * set, the browser doesn't guarantee to conform to it. */
+ PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE = 2
+} PP_TCPSocket_Option_Dev;
+PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_TCPSocket_Option_Dev, 4);
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup Interfaces
+ * @{
+ */
+/**
+ * The <code>PPB_TCPSocket_Dev</code> interface provides TCP socket operations.
+ */
+struct PPB_TCPSocket_Dev_0_1 {
+ /**
+ * Allocates a TCP socket resource.
+ */
+ PP_Resource (*Create)(PP_Instance instance);
+ /**
+ * Determines if a given resource is TCP socket.
+ */
+ PP_Bool (*IsTCPSocket)(PP_Resource resource);
+ /**
+ * Connects to an address given by |addr|, which is a PPB_NetAddress_Dev
+ * resource.
+ */
+ int32_t (*Connect)(PP_Resource tcp_socket,
+ PP_Resource addr,
+ struct PP_CompletionCallback callback);
+ /**
+ * Gets the local address of the socket, if it has been connected.
+ * Returns a PPB_NetAddress_Dev resource on success; returns 0 on failure.
+ */
+ PP_Resource (*GetLocalAddress)(PP_Resource tcp_socket);
+ /**
+ * Gets the remote address of the socket, if it has been connected.
+ * Returns a PPB_NetAddress_Dev resource on success; returns 0 on failure.
+ */
+ PP_Resource (*GetRemoteAddress)(PP_Resource tcp_socket);
+ /**
+ * Reads data from the socket. The size of |buffer| must be at least as large
+ * as |bytes_to_read|. May perform a partial read. Returns the number of bytes
+ * read or an error code. If the return value is 0, then it indicates that
+ * end-of-file was reached.
+ *
+ * Multiple outstanding read requests are not supported.
+ */
+ int32_t (*Read)(PP_Resource tcp_socket,
+ char* buffer,
+ int32_t bytes_to_read,
+ struct PP_CompletionCallback callback);
+ /**
+ * Writes data to the socket. May perform a partial write. Returns the number
+ * of bytes written or an error code.
+ *
+ * Multiple outstanding write requests are not supported.
+ */
+ int32_t (*Write)(PP_Resource tcp_socket,
+ const char* buffer,
+ int32_t bytes_to_write,
+ struct PP_CompletionCallback callback);
+ /**
+ * Cancels any IO that may be pending, and disconnects the socket. Any pending
+ * callbacks will still run, reporting PP_ERROR_ABORTED if pending IO was
+ * interrupted. It is NOT valid to call Connect() again after a call to this
+ * method. Note: If the socket is destroyed when it is still connected, then
+ * it will be implicitly disconnected, so you are not required to call this
+ * method.
+ */
+ void (*Close)(PP_Resource tcp_socket);
+ /**
+ * Sets an option on |tcp_socket|. Supported |name| and |value| parameters
+ * are as described for PP_TCPSocketOption_Dev. |callback| will be
+ * invoked with PP_OK if setting the option succeeds, or an error code
+ * otherwise. The socket must be connected before SetOption is called.
+ */
+ int32_t (*SetOption)(PP_Resource tcp_socket,
+ PP_TCPSocket_Option_Dev name,
+ struct PP_Var value,
+ struct PP_CompletionCallback callback);
+};
+
+typedef struct PPB_TCPSocket_Dev_0_1 PPB_TCPSocket_Dev;
+/**
+ * @}
+ */
+
+#endif /* PPAPI_C_DEV_PPB_TCP_SOCKET_DEV_H_ */
+
diff --git a/ppapi/cpp/dev/tcp_socket_dev.cc b/ppapi/cpp/dev/tcp_socket_dev.cc
new file mode 100644
index 0000000..4ff9514
--- /dev/null
+++ b/ppapi/cpp/dev/tcp_socket_dev.cc
@@ -0,0 +1,117 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/cpp/dev/tcp_socket_dev.h"
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/cpp/instance_handle.h"
+#include "ppapi/cpp/module_impl.h"
+
+namespace pp {
+
+namespace {
+
+template <> const char* interface_name<PPB_TCPSocket_Dev_0_1>() {
+ return PPB_TCPSOCKET_DEV_INTERFACE_0_1;
+}
+
+} // namespace
+
+TCPSocket_Dev::TCPSocket_Dev() {
+}
+
+TCPSocket_Dev::TCPSocket_Dev(const InstanceHandle& instance) {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>()) {
+ PassRefFromConstructor(get_interface<PPB_TCPSocket_Dev_0_1>()->Create(
+ instance.pp_instance()));
+ }
+}
+
+TCPSocket_Dev::TCPSocket_Dev(PassRef, PP_Resource resource)
+ : Resource(PASS_REF, resource) {
+}
+
+TCPSocket_Dev::TCPSocket_Dev(const TCPSocket_Dev& other) : Resource(other) {
+}
+
+TCPSocket_Dev::~TCPSocket_Dev() {
+}
+
+TCPSocket_Dev& TCPSocket_Dev::operator=(const TCPSocket_Dev& other) {
+ Resource::operator=(other);
+ return *this;
+}
+
+// static
+bool TCPSocket_Dev::IsAvailable() {
+ return has_interface<PPB_TCPSocket_Dev_0_1>();
+}
+
+int32_t TCPSocket_Dev::Connect(const NetAddress_Dev& addr,
+ const CompletionCallback& callback) {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>()) {
+ return get_interface<PPB_TCPSocket_Dev_0_1>()->Connect(
+ pp_resource(), addr.pp_resource(), callback.pp_completion_callback());
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
+}
+
+NetAddress_Dev TCPSocket_Dev::GetLocalAddress() const {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>()) {
+ return NetAddress_Dev(
+ PASS_REF,
+ get_interface<PPB_TCPSocket_Dev_0_1>()->GetLocalAddress(pp_resource()));
+ }
+ return NetAddress_Dev();
+}
+
+NetAddress_Dev TCPSocket_Dev::GetRemoteAddress() const {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>()) {
+ return NetAddress_Dev(
+ PASS_REF,
+ get_interface<PPB_TCPSocket_Dev_0_1>()->GetRemoteAddress(
+ pp_resource()));
+ }
+ return NetAddress_Dev();
+}
+
+int32_t TCPSocket_Dev::Read(char* buffer,
+ int32_t bytes_to_read,
+ const CompletionCallback& callback) {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>()) {
+ return get_interface<PPB_TCPSocket_Dev_0_1>()->Read(
+ pp_resource(), buffer, bytes_to_read,
+ callback.pp_completion_callback());
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
+}
+
+int32_t TCPSocket_Dev::Write(const char* buffer,
+ int32_t bytes_to_write,
+ const CompletionCallback& callback) {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>()) {
+ return get_interface<PPB_TCPSocket_Dev_0_1>()->Write(
+ pp_resource(), buffer, bytes_to_write,
+ callback.pp_completion_callback());
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
+}
+
+void TCPSocket_Dev::Close() {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>())
+ get_interface<PPB_TCPSocket_Dev_0_1>()->Close(pp_resource());
+}
+
+int32_t TCPSocket_Dev::SetOption(PP_TCPSocket_Option_Dev name,
+ const Var& value,
+ const CompletionCallback& callback) {
+ if (has_interface<PPB_TCPSocket_Dev_0_1>()) {
+ return get_interface<PPB_TCPSocket_Dev_0_1>()->SetOption(
+ pp_resource(), name, value.pp_var(), callback.pp_completion_callback());
+ }
+ return callback.MayForce(PP_ERROR_NOINTERFACE);
+}
+
+} // namespace pp
diff --git a/ppapi/cpp/dev/tcp_socket_dev.h b/ppapi/cpp/dev/tcp_socket_dev.h
new file mode 100644
index 0000000..16d7dee
--- /dev/null
+++ b/ppapi/cpp/dev/tcp_socket_dev.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_CPP_DEV_TCP_SOCKET_DEV_H_
+#define PPAPI_CPP_DEV_TCP_SOCKET_DEV_H_
+
+#include "ppapi/c/dev/ppb_tcp_socket_dev.h"
+#include "ppapi/cpp/dev/net_address_dev.h"
+#include "ppapi/cpp/pass_ref.h"
+#include "ppapi/cpp/resource.h"
+
+namespace pp {
+
+class CompletionCallback;
+class InstanceHandle;
+
+class TCPSocket_Dev: public Resource {
+ public:
+ TCPSocket_Dev();
+
+ explicit TCPSocket_Dev(const InstanceHandle& instance);
+
+ TCPSocket_Dev(PassRef, PP_Resource resource);
+
+ TCPSocket_Dev(const TCPSocket_Dev& other);
+
+ virtual ~TCPSocket_Dev();
+
+ TCPSocket_Dev& operator=(const TCPSocket_Dev& other);
+
+ // Returns true if the required interface is available.
+ static bool IsAvailable();
+
+ int32_t Connect(const NetAddress_Dev& addr,
+ const CompletionCallback& callback);
+ NetAddress_Dev GetLocalAddress() const;
+ NetAddress_Dev GetRemoteAddress() const;
+ int32_t Read(char* buffer,
+ int32_t bytes_to_read,
+ const CompletionCallback& callback);
+ int32_t Write(const char* buffer,
+ int32_t bytes_to_write,
+ const CompletionCallback& callback);
+ void Close();
+ int32_t SetOption(PP_TCPSocket_Option_Dev name,
+ const Var& value,
+ const CompletionCallback& callback);
+};
+
+} // namespace pp
+
+#endif // PPAPI_CPP_DEV_TCP_SOCKET_DEV_H_
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
index 5f45879..194925e 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -23,6 +23,7 @@
#include "ppapi/c/dev/ppb_printing_dev.h"
#include "ppapi/c/dev/ppb_resource_array_dev.h"
#include "ppapi/c/dev/ppb_scrollbar_dev.h"
+#include "ppapi/c/dev/ppb_tcp_socket_dev.h"
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/dev/ppb_text_input_dev.h"
#include "ppapi/c/dev/ppb_trace_event_dev.h"
@@ -198,6 +199,7 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_NetAddress_Dev_0_1;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Printing_Dev_0_7;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_ResourceArray_Dev_0_1;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Scrollbar_Dev_0_5;
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Testing_Dev_0_7;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Testing_Dev_0_8;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Testing_Dev_0_9;
@@ -1717,6 +1719,55 @@ static int32_t Pnacl_M23_PPB_Printing_Dev_GetDefaultPrintSettings(PP_Resource re
/* Not generating wrapper methods for PPB_Scrollbar_Dev_0_5 */
+/* Begin wrapper methods for PPB_TCPSocket_Dev_0_1 */
+
+static PP_Resource Pnacl_M29_PPB_TCPSocket_Dev_Create(PP_Instance instance) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->Create(instance);
+}
+
+static PP_Bool Pnacl_M29_PPB_TCPSocket_Dev_IsTCPSocket(PP_Resource resource) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->IsTCPSocket(resource);
+}
+
+static int32_t Pnacl_M29_PPB_TCPSocket_Dev_Connect(PP_Resource tcp_socket, PP_Resource addr, struct PP_CompletionCallback* callback) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->Connect(tcp_socket, addr, *callback);
+}
+
+static PP_Resource Pnacl_M29_PPB_TCPSocket_Dev_GetLocalAddress(PP_Resource tcp_socket) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->GetLocalAddress(tcp_socket);
+}
+
+static PP_Resource Pnacl_M29_PPB_TCPSocket_Dev_GetRemoteAddress(PP_Resource tcp_socket) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->GetRemoteAddress(tcp_socket);
+}
+
+static int32_t Pnacl_M29_PPB_TCPSocket_Dev_Read(PP_Resource tcp_socket, char* buffer, int32_t bytes_to_read, struct PP_CompletionCallback* callback) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->Read(tcp_socket, buffer, bytes_to_read, *callback);
+}
+
+static int32_t Pnacl_M29_PPB_TCPSocket_Dev_Write(PP_Resource tcp_socket, const char* buffer, int32_t bytes_to_write, struct PP_CompletionCallback* callback) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->Write(tcp_socket, buffer, bytes_to_write, *callback);
+}
+
+static void Pnacl_M29_PPB_TCPSocket_Dev_Close(PP_Resource tcp_socket) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ iface->Close(tcp_socket);
+}
+
+static int32_t Pnacl_M29_PPB_TCPSocket_Dev_SetOption(PP_Resource tcp_socket, PP_TCPSocket_Option_Dev name, struct PP_Var* value, struct PP_CompletionCallback* callback) {
+ const struct PPB_TCPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1.real_iface;
+ return iface->SetOption(tcp_socket, name, *value, *callback);
+}
+
+/* End wrapper methods for PPB_TCPSocket_Dev_0_1 */
+
/* Not generating wrapper methods for PPB_Testing_Dev_0_7 */
/* Not generating wrapper methods for PPB_Testing_Dev_0_8 */
@@ -4183,6 +4234,18 @@ struct PPB_Printing_Dev_0_7 Pnacl_Wrappers_PPB_Printing_Dev_0_7 = {
/* Not generating wrapper interface for PPB_Scrollbar_Dev_0_5 */
+struct PPB_TCPSocket_Dev_0_1 Pnacl_Wrappers_PPB_TCPSocket_Dev_0_1 = {
+ .Create = (PP_Resource (*)(PP_Instance instance))&Pnacl_M29_PPB_TCPSocket_Dev_Create,
+ .IsTCPSocket = (PP_Bool (*)(PP_Resource resource))&Pnacl_M29_PPB_TCPSocket_Dev_IsTCPSocket,
+ .Connect = (int32_t (*)(PP_Resource tcp_socket, PP_Resource addr, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_TCPSocket_Dev_Connect,
+ .GetLocalAddress = (PP_Resource (*)(PP_Resource tcp_socket))&Pnacl_M29_PPB_TCPSocket_Dev_GetLocalAddress,
+ .GetRemoteAddress = (PP_Resource (*)(PP_Resource tcp_socket))&Pnacl_M29_PPB_TCPSocket_Dev_GetRemoteAddress,
+ .Read = (int32_t (*)(PP_Resource tcp_socket, char* buffer, int32_t bytes_to_read, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_TCPSocket_Dev_Read,
+ .Write = (int32_t (*)(PP_Resource tcp_socket, const char* buffer, int32_t bytes_to_write, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_TCPSocket_Dev_Write,
+ .Close = (void (*)(PP_Resource tcp_socket))&Pnacl_M29_PPB_TCPSocket_Dev_Close,
+ .SetOption = (int32_t (*)(PP_Resource tcp_socket, PP_TCPSocket_Option_Dev name, struct PP_Var value, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_TCPSocket_Dev_SetOption
+};
+
/* Not generating wrapper interface for PPB_Testing_Dev_0_7 */
/* Not generating wrapper interface for PPB_Testing_Dev_0_8 */
@@ -5160,6 +5223,12 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Scrollbar_Dev_0_5 = {
.real_iface = NULL
};
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1 = {
+ .iface_macro = PPB_TCPSOCKET_DEV_INTERFACE_0_1,
+ .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_TCPSocket_Dev_0_1,
+ .real_iface = NULL
+};
+
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Testing_Dev_0_7 = {
.iface_macro = PPB_TESTING_DEV_INTERFACE_0_7,
.wrapped_iface = NULL /* Still need slot for real_iface */,
@@ -5710,6 +5779,7 @@ static struct __PnaclWrapperInfo *s_ppb_wrappers[] = {
&Pnacl_WrapperInfo_PPB_Printing_Dev_0_7,
&Pnacl_WrapperInfo_PPB_ResourceArray_Dev_0_1,
&Pnacl_WrapperInfo_PPB_Scrollbar_Dev_0_5,
+ &Pnacl_WrapperInfo_PPB_TCPSocket_Dev_0_1,
&Pnacl_WrapperInfo_PPB_Testing_Dev_0_7,
&Pnacl_WrapperInfo_PPB_Testing_Dev_0_8,
&Pnacl_WrapperInfo_PPB_Testing_Dev_0_9,
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index 16bfe48..b71178c 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -123,6 +123,8 @@
'proxy/ppb_network_monitor_private_proxy.h',
'proxy/ppb_tcp_server_socket_private_proxy.cc',
'proxy/ppb_tcp_server_socket_private_proxy.h',
+ 'proxy/ppb_tcp_socket_proxy.cc',
+ 'proxy/ppb_tcp_socket_proxy.h',
'proxy/ppb_tcp_socket_private_proxy.cc',
'proxy/ppb_tcp_socket_private_proxy.h',
'proxy/ppb_testing_proxy.cc',
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 34cff29..a834433 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -94,6 +94,8 @@
'shared_impl/scoped_pp_resource.h',
'shared_impl/scoped_pp_var.cc',
'shared_impl/scoped_pp_var.h',
+ 'shared_impl/tcp_socket_shared.cc',
+ 'shared_impl/tcp_socket_shared.h',
'shared_impl/thread_aware_callback.cc',
'shared_impl/thread_aware_callback.h',
'shared_impl/time_conversion.cc',
@@ -219,6 +221,8 @@
'thunk/ppb_talk_private_thunk.cc',
'thunk/ppb_tcp_server_socket_private_api.h',
'thunk/ppb_tcp_server_socket_private_thunk.cc',
+ 'thunk/ppb_tcp_socket_api.h',
+ 'thunk/ppb_tcp_socket_dev_thunk.cc',
'thunk/ppb_tcp_socket_private_api.h',
'thunk/ppb_tcp_socket_private_thunk.cc',
'thunk/ppb_text_input_thunk.cc',
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index df92b53..4c6d666 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -73,6 +73,7 @@
'c/dev/ppb_printing_dev.h',
'c/dev/ppb_resource_array_dev.h',
'c/dev/ppb_scrollbar_dev.h',
+ 'c/dev/ppb_tcp_socket_dev.h',
'c/dev/ppb_testing_dev.h',
'c/dev/ppb_text_input_dev.h',
'c/dev/ppb_truetype_font_dev.h',
@@ -240,6 +241,8 @@
'cpp/dev/scrollbar_dev.h',
'cpp/dev/selection_dev.cc',
'cpp/dev/selection_dev.h',
+ 'cpp/dev/tcp_socket_dev.cc',
+ 'cpp/dev/tcp_socket_dev.h',
'cpp/dev/text_input_dev.cc',
'cpp/dev/text_input_dev.h',
'cpp/dev/truetype_font_dev.cc',
@@ -441,6 +444,8 @@
'tests/test_scrollbar.h',
'tests/test_tcp_server_socket_private.cc',
'tests/test_tcp_server_socket_private.h',
+ 'tests/test_tcp_socket.cc',
+ 'tests/test_tcp_socket.h',
'tests/test_tcp_socket_private.cc',
'tests/test_tcp_socket_private.h',
'tests/test_truetype_font.cc',
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc
index 864de88..0a62aa1 100644
--- a/ppapi/proxy/interface_list.cc
+++ b/ppapi/proxy/interface_list.cc
@@ -22,6 +22,7 @@
#include "ppapi/c/dev/ppb_opengles2ext_dev.h"
#include "ppapi/c/dev/ppb_printing_dev.h"
#include "ppapi/c/dev/ppb_resource_array_dev.h"
+#include "ppapi/c/dev/ppb_tcp_socket_dev.h"
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/dev/ppb_text_input_dev.h"
#include "ppapi/c/dev/ppb_trace_event_dev.h"
@@ -105,6 +106,7 @@
#include "ppapi/proxy/ppb_network_monitor_private_proxy.h"
#include "ppapi/proxy/ppb_tcp_server_socket_private_proxy.h"
#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
+#include "ppapi/proxy/ppb_tcp_socket_proxy.h"
#include "ppapi/proxy/ppb_testing_proxy.h"
#include "ppapi/proxy/ppb_var_deprecated_proxy.h"
#include "ppapi/proxy/ppb_video_decoder_proxy.h"
diff --git a/ppapi/proxy/ppb_tcp_socket_private_proxy.h b/ppapi/proxy/ppb_tcp_socket_private_proxy.h
index ffceca7..6f0f0f4 100644
--- a/ppapi/proxy/ppb_tcp_socket_private_proxy.h
+++ b/ppapi/proxy/ppb_tcp_socket_private_proxy.h
@@ -22,7 +22,7 @@ namespace proxy {
class PPB_TCPSocket_Private_Proxy : public InterfaceProxy {
public:
- PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher);
+ explicit PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher);
virtual ~PPB_TCPSocket_Private_Proxy();
static PP_Resource CreateProxyResource(PP_Instance instance);
diff --git a/ppapi/proxy/ppb_tcp_socket_proxy.cc b/ppapi/proxy/ppb_tcp_socket_proxy.cc
new file mode 100644
index 0000000..1b6bd8a
--- /dev/null
+++ b/ppapi/proxy/ppb_tcp_socket_proxy.cc
@@ -0,0 +1,303 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/proxy/ppb_tcp_socket_proxy.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/tcp_socket_shared.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_net_address_api.h"
+#include "ppapi/thunk/ppb_tcp_socket_api.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+typedef thunk::EnterResourceNoLock<thunk::PPB_NetAddress_API>
+ EnterNetAddressNoLock;
+
+typedef std::map<uint32, TCPSocketShared*> IDToSocketMap;
+IDToSocketMap* g_id_to_socket = NULL;
+
+class TCPSocket : public thunk::PPB_TCPSocket_API,
+ public Resource,
+ public TCPSocketShared {
+ public:
+ TCPSocket(const HostResource& resource, uint32 socket_id);
+ virtual ~TCPSocket();
+
+ // Resource overrides.
+ virtual thunk::PPB_TCPSocket_API* AsPPB_TCPSocket_API() OVERRIDE;
+
+ // thunk::PPB_TCPSocket_API implementation.
+ virtual int32_t Connect(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual PP_Resource GetLocalAddress() OVERRIDE;
+ virtual PP_Resource GetRemoteAddress() OVERRIDE;
+ virtual int32_t Read(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual int32_t Write(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual int32_t SetOption(PP_TCPSocket_Option_Dev name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
+ // TCPSocketShared implementation.
+ virtual void SendConnect(const std::string& host, uint16_t port) OVERRIDE;
+ virtual void SendConnectWithNetAddress(
+ const PP_NetAddress_Private& addr) OVERRIDE;
+ virtual void SendSSLHandshake(
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) OVERRIDE;
+ virtual void SendRead(int32_t bytes_to_read) OVERRIDE;
+ virtual void SendWrite(const std::string& buffer) OVERRIDE;
+ virtual void SendDisconnect() OVERRIDE;
+ virtual void SendSetBoolOption(PP_TCPSocketOption_Private name,
+ bool value) OVERRIDE;
+ virtual Resource* GetOwnerResource() OVERRIDE;
+
+ private:
+ void SendToBrowser(IPC::Message* msg);
+
+ DISALLOW_COPY_AND_ASSIGN(TCPSocket);
+};
+
+TCPSocket::TCPSocket(const HostResource& resource, uint32 socket_id)
+ : Resource(OBJECT_IS_PROXY, resource),
+ TCPSocketShared(OBJECT_IS_PROXY, socket_id) {
+ if (!g_id_to_socket)
+ g_id_to_socket = new IDToSocketMap();
+ DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end());
+ (*g_id_to_socket)[socket_id] = this;
+}
+
+TCPSocket::~TCPSocket() {
+ DisconnectImpl();
+}
+
+thunk::PPB_TCPSocket_API* TCPSocket::AsPPB_TCPSocket_API() {
+ return this;
+}
+
+int32_t TCPSocket::Connect(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) {
+ EnterNetAddressNoLock enter(addr, true);
+ if (enter.failed())
+ return PP_ERROR_BADARGUMENT;
+
+ return ConnectWithNetAddressImpl(&enter.object()->GetNetAddressPrivate(),
+ callback);
+}
+
+PP_Resource TCPSocket::GetLocalAddress() {
+ PP_NetAddress_Private addr_private;
+ if (!GetLocalAddressImpl(&addr_private))
+ return 0;
+
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ if (enter.failed())
+ return 0;
+ return enter.functions()->CreateNetAddressFromNetAddressPrivate(
+ pp_instance(), addr_private);
+}
+
+PP_Resource TCPSocket::GetRemoteAddress() {
+ PP_NetAddress_Private addr_private;
+ if (!GetRemoteAddressImpl(&addr_private))
+ return 0;
+
+ thunk::EnterResourceCreationNoLock enter(pp_instance());
+ if (enter.failed())
+ return 0;
+ return enter.functions()->CreateNetAddressFromNetAddressPrivate(
+ pp_instance(), addr_private);
+}
+
+int32_t TCPSocket::Read(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) {
+ return ReadImpl(buffer, bytes_to_read, callback);
+}
+
+int32_t TCPSocket::Write(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) {
+ return WriteImpl(buffer, bytes_to_write, callback);
+}
+
+void TCPSocket::Close() {
+ DisconnectImpl();
+}
+
+int32_t TCPSocket::SetOption(PP_TCPSocket_Option_Dev name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) {
+ // TODO(yzshen): Add support for other options.
+ if (name == PP_TCPSOCKET_OPTION_NO_DELAY)
+ return SetOptionImpl(PP_TCPSOCKETOPTION_NO_DELAY, value, callback);
+
+ return PP_ERROR_NOTSUPPORTED;
+}
+
+void TCPSocket::SendConnect(const std::string& host, uint16_t port) {
+ NOTREACHED();
+}
+
+void TCPSocket::SendConnectWithNetAddress(const PP_NetAddress_Private& addr) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
+ API_ID_PPB_TCPSOCKET, socket_id_, addr));
+}
+
+void TCPSocket::SendSSLHandshake(
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) {
+ NOTREACHED();
+}
+
+void TCPSocket::SendRead(int32_t bytes_to_read) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read));
+}
+
+void TCPSocket::SendWrite(const std::string& buffer) {
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Write(socket_id_, buffer));
+}
+
+void TCPSocket::SendDisconnect() {
+ // After removed from the mapping, this object won't receive any notifications
+ // from the proxy.
+ DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end());
+ g_id_to_socket->erase(socket_id_);
+ SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_));
+}
+
+void TCPSocket::SendSetBoolOption(PP_TCPSocketOption_Private name, bool value) {
+ SendToBrowser(
+ new PpapiHostMsg_PPBTCPSocket_SetBoolOption(socket_id_, name, value));
+}
+
+Resource* TCPSocket::GetOwnerResource() {
+ return this;
+}
+
+void TCPSocket::SendToBrowser(IPC::Message* msg) {
+ PluginGlobals::Get()->GetBrowserSender()->Send(msg);
+}
+
+} // namespace
+
+//------------------------------------------------------------------------------
+
+PPB_TCPSocket_Proxy::PPB_TCPSocket_Proxy(Dispatcher* dispatcher)
+ : InterfaceProxy(dispatcher) {
+}
+
+PPB_TCPSocket_Proxy::~PPB_TCPSocket_Proxy() {
+}
+
+// static
+PP_Resource PPB_TCPSocket_Proxy::CreateProxyResource(PP_Instance instance) {
+ PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
+ if (!dispatcher)
+ return 0;
+
+ uint32 socket_id = 0;
+ PluginGlobals::Get()->GetBrowserSender()->Send(
+ new PpapiHostMsg_PPBTCPSocket_Create(
+ API_ID_PPB_TCPSOCKET, dispatcher->plugin_dispatcher_id(),
+ &socket_id));
+ if (socket_id == 0)
+ return 0;
+ return (new TCPSocket(HostResource::MakeInstanceOnly(instance),
+ socket_id))->GetReference();
+}
+
+bool PPB_TCPSocket_Proxy::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PPB_TCPSocket_Proxy, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK,
+ OnMsgConnectACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK, OnMsgReadACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK, OnMsgWriteACK)
+ IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetBoolOptionACK,
+ OnMsgSetBoolOptionACK)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PPB_TCPSocket_Proxy::OnMsgConnectACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ if (!g_id_to_socket) {
+ NOTREACHED();
+ return;
+ }
+ IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
+ if (iter == g_id_to_socket->end())
+ return;
+ iter->second->OnConnectCompleted(succeeded, local_addr, remote_addr);
+}
+
+void PPB_TCPSocket_Proxy::OnMsgReadACK(uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded,
+ const std::string& data) {
+ if (!g_id_to_socket) {
+ NOTREACHED();
+ return;
+ }
+ IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
+ if (iter == g_id_to_socket->end())
+ return;
+ iter->second->OnReadCompleted(succeeded, data);
+}
+
+void PPB_TCPSocket_Proxy::OnMsgWriteACK(uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded,
+ int32_t bytes_written) {
+ if (!g_id_to_socket) {
+ NOTREACHED();
+ return;
+ }
+ IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
+ if (iter == g_id_to_socket->end())
+ return;
+ iter->second->OnWriteCompleted(succeeded, bytes_written);
+}
+
+void PPB_TCPSocket_Proxy::OnMsgSetBoolOptionACK(
+ uint32 /* plugin_dispatcher_id */,
+ uint32 socket_id,
+ bool succeeded) {
+ if (!g_id_to_socket) {
+ NOTREACHED();
+ return;
+ }
+ IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
+ if (iter == g_id_to_socket->end())
+ return;
+ iter->second->OnSetOptionCompleted(succeeded);
+}
+
+} // namespace proxy
+} // namespace ppapi
diff --git a/ppapi/proxy/ppb_tcp_socket_proxy.h b/ppapi/proxy/ppb_tcp_socket_proxy.h
new file mode 100644
index 0000000..35314a3
--- /dev/null
+++ b/ppapi/proxy/ppb_tcp_socket_proxy.h
@@ -0,0 +1,58 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_PROXY_PPB_TCP_SOCKET_PROXY_H_
+#define PPAPI_PROXY_PPB_TCP_SOCKET_PROXY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/proxy/interface_proxy.h"
+#include "ppapi/proxy/ppapi_proxy_export.h"
+
+struct PP_NetAddress_Private;
+
+namespace ppapi {
+namespace proxy {
+
+class PPB_TCPSocket_Proxy : public InterfaceProxy {
+ public:
+ explicit PPB_TCPSocket_Proxy(Dispatcher* dispatcher);
+ virtual ~PPB_TCPSocket_Proxy();
+
+ static PP_Resource CreateProxyResource(PP_Instance instance);
+
+ // InterfaceProxy implementation.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ static const ApiID kApiID = API_ID_PPB_TCPSOCKET;
+
+ private:
+ // Browser->plugin message handlers.
+ void OnMsgConnectACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void OnMsgReadACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded,
+ const std::string& data);
+ void OnMsgWriteACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded,
+ int32_t bytes_written);
+ void OnMsgSetBoolOptionACK(uint32 plugin_dispatcher_id,
+ uint32 socket_id,
+ bool succeeded);
+
+ DISALLOW_COPY_AND_ASSIGN(PPB_TCPSocket_Proxy);
+};
+
+} // namespace proxy
+} // namespace ppapi
+
+#endif // PPAPI_PROXY_PPB_TCP_SOCKET_PROXY_H_
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
index 3448ce7..a9300cce 100644
--- a/ppapi/proxy/resource_creation_proxy.cc
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -33,6 +33,7 @@
#include "ppapi/proxy/ppb_network_monitor_private_proxy.h"
#include "ppapi/proxy/ppb_tcp_server_socket_private_proxy.h"
#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
+#include "ppapi/proxy/ppb_tcp_socket_proxy.h"
#include "ppapi/proxy/ppb_video_decoder_proxy.h"
#include "ppapi/proxy/ppb_x509_certificate_private_proxy.h"
#include "ppapi/proxy/printing_resource.h"
@@ -278,6 +279,13 @@ PP_Resource ResourceCreationProxy::CreateNetAddressFromIPv6Address(
*ipv6_addr))->GetReference();
}
+PP_Resource ResourceCreationProxy::CreateNetAddressFromNetAddressPrivate(
+ PP_Instance instance,
+ const PP_NetAddress_Private& private_addr) {
+ return (new NetAddressResource(GetConnection(), instance,
+ private_addr))->GetReference();
+}
+
PP_Resource ResourceCreationProxy::CreateNetworkMonitor(
PP_Instance instance,
PPB_NetworkMonitor_Callback callback,
@@ -295,6 +303,11 @@ PP_Resource ResourceCreationProxy::CreateTCPServerSocketPrivate(
return PPB_TCPServerSocket_Private_Proxy::CreateProxyResource(instance);
}
+PP_Resource ResourceCreationProxy::CreateTCPSocket(
+ PP_Instance instance) {
+ return PPB_TCPSocket_Proxy::CreateProxyResource(instance);
+}
+
PP_Resource ResourceCreationProxy::CreateTCPSocketPrivate(
PP_Instance instance) {
return PPB_TCPSocket_Private_Proxy::CreateProxyResource(instance);
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
index 3dd514d..d00a8bd 100644
--- a/ppapi/proxy/resource_creation_proxy.h
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -128,6 +128,9 @@ class ResourceCreationProxy : public InterfaceProxy,
virtual PP_Resource CreateNetAddressFromIPv6Address(
PP_Instance instance,
const PP_NetAddress_IPv6_Dev* ipv6_addr) OVERRIDE;
+ virtual PP_Resource CreateNetAddressFromNetAddressPrivate(
+ PP_Instance instance,
+ const PP_NetAddress_Private& private_addr) OVERRIDE;
virtual PP_Resource CreateNetworkMonitor(
PP_Instance instance,
PPB_NetworkMonitor_Callback callback,
@@ -135,6 +138,7 @@ class ResourceCreationProxy : public InterfaceProxy,
virtual PP_Resource CreatePrinting(PP_Instance) OVERRIDE;
virtual PP_Resource CreateTCPServerSocketPrivate(
PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateTCPSocket(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateWebSocket(PP_Instance instance) OVERRIDE;
diff --git a/ppapi/shared_impl/api_id.h b/ppapi/shared_impl/api_id.h
index 16955aa..65a150e 100644
--- a/ppapi/shared_impl/api_id.h
+++ b/ppapi/shared_impl/api_id.h
@@ -40,6 +40,7 @@ enum ApiID {
API_ID_PPB_PDF,
API_ID_PPB_SURFACE_3D,
API_ID_PPB_TCPSERVERSOCKET_PRIVATE,
+ API_ID_PPB_TCPSOCKET,
API_ID_PPB_TCPSOCKET_PRIVATE,
API_ID_PPB_TALK,
API_ID_PPB_TESTING,
diff --git a/ppapi/shared_impl/private/tcp_socket_private_impl.cc b/ppapi/shared_impl/private/tcp_socket_private_impl.cc
index 87cc600..832603c 100644
--- a/ppapi/shared_impl/private/tcp_socket_private_impl.cc
+++ b/ppapi/shared_impl/private/tcp_socket_private_impl.cc
@@ -4,40 +4,18 @@
#include "ppapi/shared_impl/private/tcp_socket_private_impl.h"
-#include <string.h>
-
-#include <algorithm>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "ppapi/c/pp_completion_callback.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/shared_impl/ppapi_globals.h"
-#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
-#include "ppapi/shared_impl/var_tracker.h"
-#include "ppapi/shared_impl/var.h"
-#include "ppapi/thunk/enter.h"
-#include "ppapi/thunk/ppb_x509_certificate_private_api.h"
-
namespace ppapi {
-const int32_t TCPSocketPrivateImpl::kMaxReadSize = 1024 * 1024;
-const int32_t TCPSocketPrivateImpl::kMaxWriteSize = 1024 * 1024;
-
TCPSocketPrivateImpl::TCPSocketPrivateImpl(PP_Instance instance,
uint32 socket_id)
: Resource(OBJECT_IS_IMPL, instance),
- resource_type_(OBJECT_IS_IMPL) {
- Init(socket_id);
+ TCPSocketShared(OBJECT_IS_IMPL, socket_id) {
}
TCPSocketPrivateImpl::TCPSocketPrivateImpl(const HostResource& resource,
uint32 socket_id)
: Resource(OBJECT_IS_PROXY, resource),
- resource_type_(OBJECT_IS_PROXY) {
- Init(socket_id);
+ TCPSocketShared(OBJECT_IS_PROXY, socket_id) {
}
TCPSocketPrivateImpl::~TCPSocketPrivateImpl() {
@@ -51,303 +29,67 @@ TCPSocketPrivateImpl::AsPPB_TCPSocket_Private_API() {
int32_t TCPSocketPrivateImpl::Connect(const char* host,
uint16_t port,
scoped_refptr<TrackedCallback> callback) {
- if (!host)
- return PP_ERROR_BADARGUMENT;
- if (connection_state_ != BEFORE_CONNECT)
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(connect_callback_))
- return PP_ERROR_INPROGRESS; // Can only have one pending request.
-
- connect_callback_ = callback;
- // Send the request, the browser will call us back via ConnectACK.
- SendConnect(host, port);
- return PP_OK_COMPLETIONPENDING;
+ return ConnectImpl(host, port, callback);
}
int32_t TCPSocketPrivateImpl::ConnectWithNetAddress(
const PP_NetAddress_Private* addr,
scoped_refptr<TrackedCallback> callback) {
- if (!addr)
- return PP_ERROR_BADARGUMENT;
- if (connection_state_ != BEFORE_CONNECT)
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(connect_callback_))
- return PP_ERROR_INPROGRESS; // Can only have one pending request.
-
- connect_callback_ = callback;
- // Send the request, the browser will call us back via ConnectACK.
- SendConnectWithNetAddress(*addr);
- return PP_OK_COMPLETIONPENDING;
+ return ConnectWithNetAddressImpl(addr, callback);
}
PP_Bool TCPSocketPrivateImpl::GetLocalAddress(
PP_NetAddress_Private* local_addr) {
- if (!IsConnected() || !local_addr)
- return PP_FALSE;
-
- *local_addr = local_addr_;
- return PP_TRUE;
+ return GetLocalAddressImpl(local_addr);
}
PP_Bool TCPSocketPrivateImpl::GetRemoteAddress(
PP_NetAddress_Private* remote_addr) {
- if (!IsConnected() || !remote_addr)
- return PP_FALSE;
-
- *remote_addr = remote_addr_;
- return PP_TRUE;
+ return GetRemoteAddressImpl(remote_addr);
}
int32_t TCPSocketPrivateImpl::SSLHandshake(
const char* server_name,
uint16_t server_port,
scoped_refptr<TrackedCallback> callback) {
- if (!server_name)
- return PP_ERROR_BADARGUMENT;
-
- if (connection_state_ != CONNECTED)
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(ssl_handshake_callback_) ||
- TrackedCallback::IsPending(read_callback_) ||
- TrackedCallback::IsPending(write_callback_))
- return PP_ERROR_INPROGRESS;
-
- ssl_handshake_callback_ = callback;
-
- // Send the request, the browser will call us back via SSLHandshakeACK.
- SendSSLHandshake(server_name, server_port, trusted_certificates_,
- untrusted_certificates_);
- return PP_OK_COMPLETIONPENDING;
+ return SSLHandshakeImpl(server_name, server_port, callback);
}
PP_Resource TCPSocketPrivateImpl::GetServerCertificate() {
- if (!server_certificate_.get())
- return 0;
- return server_certificate_->GetReference();
+ return GetServerCertificateImpl();
}
PP_Bool TCPSocketPrivateImpl::AddChainBuildingCertificate(
PP_Resource certificate,
PP_Bool trusted) {
- // TODO(raymes): The plumbing for this functionality is implemented but the
- // certificates aren't yet used for the connection, so just return false for
- // now.
- return PP_FALSE;
-
- thunk::EnterResourceNoLock<thunk::PPB_X509Certificate_Private_API>
- enter_cert(certificate, true);
- if (enter_cert.failed())
- return PP_FALSE;
-
- PP_Var der_var = enter_cert.object()->GetField(
- PP_X509CERTIFICATE_PRIVATE_RAW);
- ArrayBufferVar* der_array_buffer = ArrayBufferVar::FromPPVar(der_var);
- PP_Bool success = PP_FALSE;
- if (der_array_buffer) {
- const char* der_bytes = static_cast<const char*>(der_array_buffer->Map());
- uint32_t der_length = der_array_buffer->ByteLength();
- std::vector<char> der(der_bytes, der_bytes + der_length);
- if (PP_ToBool(trusted))
- trusted_certificates_.push_back(der);
- else
- untrusted_certificates_.push_back(der);
- success = PP_TRUE;
- }
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(der_var);
- return success;
+ return AddChainBuildingCertificateImpl(certificate, trusted);
}
int32_t TCPSocketPrivateImpl::Read(char* buffer,
int32_t bytes_to_read,
scoped_refptr<TrackedCallback> callback) {
- if (!buffer || bytes_to_read <= 0)
- return PP_ERROR_BADARGUMENT;
-
- if (!IsConnected())
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(read_callback_) ||
- TrackedCallback::IsPending(ssl_handshake_callback_))
- return PP_ERROR_INPROGRESS;
- read_buffer_ = buffer;
- bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize);
- read_callback_ = callback;
-
- // Send the request, the browser will call us back via ReadACK.
- SendRead(bytes_to_read_);
- return PP_OK_COMPLETIONPENDING;
+ return ReadImpl(buffer, bytes_to_read, callback);
}
int32_t TCPSocketPrivateImpl::Write(const char* buffer,
int32_t bytes_to_write,
scoped_refptr<TrackedCallback> callback) {
- if (!buffer || bytes_to_write <= 0)
- return PP_ERROR_BADARGUMENT;
-
- if (!IsConnected())
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(write_callback_) ||
- TrackedCallback::IsPending(ssl_handshake_callback_))
- return PP_ERROR_INPROGRESS;
-
- if (bytes_to_write > kMaxWriteSize)
- bytes_to_write = kMaxWriteSize;
-
- write_callback_ = callback;
-
- // Send the request, the browser will call us back via WriteACK.
- SendWrite(std::string(buffer, bytes_to_write));
- return PP_OK_COMPLETIONPENDING;
+ return WriteImpl(buffer, bytes_to_write, callback);
}
void TCPSocketPrivateImpl::Disconnect() {
- if (connection_state_ == DISCONNECTED)
- return;
-
- connection_state_ = DISCONNECTED;
-
- SendDisconnect();
- socket_id_ = 0;
-
- PostAbortIfNecessary(&connect_callback_);
- PostAbortIfNecessary(&ssl_handshake_callback_);
- PostAbortIfNecessary(&read_callback_);
- PostAbortIfNecessary(&write_callback_);
- PostAbortIfNecessary(&set_option_callback_);
- read_buffer_ = NULL;
- bytes_to_read_ = -1;
- server_certificate_ = NULL;
+ DisconnectImpl();
}
int32_t TCPSocketPrivateImpl::SetOption(
PP_TCPSocketOption_Private name,
const PP_Var& value,
scoped_refptr<TrackedCallback> callback) {
- if (!IsConnected())
- return PP_ERROR_FAILED;
- if (TrackedCallback::IsPending(set_option_callback_))
- return PP_ERROR_INPROGRESS;
-
- set_option_callback_ = callback;
-
- switch (name) {
- case PP_TCPSOCKETOPTION_NO_DELAY:
- if (value.type != PP_VARTYPE_BOOL)
- return PP_ERROR_BADARGUMENT;
- SendSetBoolOption(name, PP_ToBool(value.value.as_bool));
- return PP_OK_COMPLETIONPENDING;
- default:
- return PP_ERROR_BADARGUMENT;
- }
-}
-
-void TCPSocketPrivateImpl::OnConnectCompleted(
- bool succeeded,
- const PP_NetAddress_Private& local_addr,
- const PP_NetAddress_Private& remote_addr) {
- if (connection_state_ != BEFORE_CONNECT ||
- !TrackedCallback::IsPending(connect_callback_)) {
- NOTREACHED();
- return;
- }
-
- if (succeeded) {
- local_addr_ = local_addr;
- remote_addr_ = remote_addr;
- connection_state_ = CONNECTED;
- }
- connect_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
-}
-
-void TCPSocketPrivateImpl::OnSSLHandshakeCompleted(
- bool succeeded,
- const PPB_X509Certificate_Fields& certificate_fields) {
- if (connection_state_ != CONNECTED ||
- !TrackedCallback::IsPending(ssl_handshake_callback_)) {
- NOTREACHED();
- return;
- }
-
- if (succeeded) {
- connection_state_ = SSL_CONNECTED;
- server_certificate_ = new PPB_X509Certificate_Private_Shared(
- resource_type_,
- pp_instance(),
- certificate_fields);
- ssl_handshake_callback_->Run(PP_OK);
- } else {
- // The resource might be released in the callback so we need to hold
- // a reference so we can Disconnect() first.
- AddRef();
- ssl_handshake_callback_->Run(PP_ERROR_FAILED);
- Disconnect();
- Release();
- }
-}
-
-void TCPSocketPrivateImpl::OnReadCompleted(bool succeeded,
- const std::string& data) {
- if (!TrackedCallback::IsPending(read_callback_) || !read_buffer_) {
- NOTREACHED();
- return;
- }
-
- if (succeeded) {
- CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
- if (!data.empty())
- memcpy(read_buffer_, data.c_str(), data.size());
- }
- read_buffer_ = NULL;
- bytes_to_read_ = -1;
-
- read_callback_->Run(
- succeeded ? static_cast<int32_t>(data.size()) :
- static_cast<int32_t>(PP_ERROR_FAILED));
+ return SetOptionImpl(name, value, callback);
}
-void TCPSocketPrivateImpl::OnWriteCompleted(bool succeeded,
- int32_t bytes_written) {
- if (!TrackedCallback::IsPending(write_callback_) ||
- (succeeded && bytes_written < 0)) {
- NOTREACHED();
- return;
- }
-
- write_callback_->Run(
- succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED));
-}
-
-void TCPSocketPrivateImpl::OnSetOptionCompleted(bool succeeded) {
- if (!TrackedCallback::IsPending(set_option_callback_)) {
- NOTREACHED();
- return;
- }
-
- set_option_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
-}
-
-void TCPSocketPrivateImpl::Init(uint32 socket_id) {
- DCHECK(socket_id != 0);
- socket_id_ = socket_id;
- connection_state_ = BEFORE_CONNECT;
- read_buffer_ = NULL;
- bytes_to_read_ = -1;
-
- local_addr_.size = 0;
- memset(local_addr_.data, 0,
- arraysize(local_addr_.data) * sizeof(*local_addr_.data));
- remote_addr_.size = 0;
- memset(remote_addr_.data, 0,
- arraysize(remote_addr_.data) * sizeof(*remote_addr_.data));
-}
-
-bool TCPSocketPrivateImpl::IsConnected() const {
- return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
-}
-
-void TCPSocketPrivateImpl::PostAbortIfNecessary(
- scoped_refptr<TrackedCallback>* callback) {
- if (TrackedCallback::IsPending(*callback))
- (*callback)->PostAbort();
+Resource* TCPSocketPrivateImpl::GetOwnerResource() {
+ return this;
}
} // namespace ppapi
diff --git a/ppapi/shared_impl/private/tcp_socket_private_impl.h b/ppapi/shared_impl/private/tcp_socket_private_impl.h
index 95057e7..62fba8e 100644
--- a/ppapi/shared_impl/private/tcp_socket_private_impl.h
+++ b/ppapi/shared_impl/private/tcp_socket_private_impl.h
@@ -5,26 +5,22 @@
#ifndef PPAPI_SHARED_IMPL_PRIVATE_TCP_SOCKET_PRIVATE_IMPL_H_
#define PPAPI_SHARED_IMPL_PRIVATE_TCP_SOCKET_PRIVATE_IMPL_H_
-#include <string>
-#include <vector>
-
+#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "ppapi/shared_impl/resource.h"
-#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/shared_impl/tcp_socket_shared.h"
#include "ppapi/thunk/ppb_tcp_socket_private_api.h"
namespace ppapi {
-class PPB_X509Certificate_Fields;
-class PPB_X509Certificate_Private_Shared;
-
// This class provides the shared implementation of a
// PPB_TCPSocket_Private. The functions that actually send messages
// to browser are implemented differently for the proxied and
// non-proxied derived classes.
class PPAPI_SHARED_EXPORT TCPSocketPrivateImpl
: public thunk::PPB_TCPSocket_Private_API,
- public Resource {
+ public Resource,
+ public TCPSocketShared {
public:
// C-tor used in Impl case.
TCPSocketPrivateImpl(PP_Instance instance, uint32 socket_id);
@@ -33,13 +29,6 @@ class PPAPI_SHARED_EXPORT TCPSocketPrivateImpl
virtual ~TCPSocketPrivateImpl();
- // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read
- // message is allowed to request.
- static const int32_t kMaxReadSize;
- // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Write
- // message is allowed to carry.
- static const int32_t kMaxWriteSize;
-
// Resource overrides.
virtual PPB_TCPSocket_Private_API* AsPPB_TCPSocket_Private_API() OVERRIDE;
@@ -70,72 +59,10 @@ class PPAPI_SHARED_EXPORT TCPSocketPrivateImpl
const PP_Var& value,
scoped_refptr<TrackedCallback> callback) OVERRIDE;
- // Notifications on operations completion.
- void OnConnectCompleted(bool succeeded,
- const PP_NetAddress_Private& local_addr,
- const PP_NetAddress_Private& remote_addr);
- void OnSSLHandshakeCompleted(
- bool succeeded,
- const PPB_X509Certificate_Fields& certificate_fields);
- void OnReadCompleted(bool succeeded, const std::string& data);
- void OnWriteCompleted(bool succeeded, int32_t bytes_written);
- void OnSetOptionCompleted(bool succeeded);
-
- // Send functions that need to be implemented differently for the
- // proxied and non-proxied derived classes.
- virtual void SendConnect(const std::string& host, uint16_t port) = 0;
- virtual void SendConnectWithNetAddress(const PP_NetAddress_Private& addr) = 0;
- virtual void SendSSLHandshake(
- const std::string& server_name,
- uint16_t server_port,
- const std::vector<std::vector<char> >& trusted_certs,
- const std::vector<std::vector<char> >& untrusted_certs) = 0;
- virtual void SendRead(int32_t bytes_to_read) = 0;
- virtual void SendWrite(const std::string& buffer) = 0;
- virtual void SendDisconnect() = 0;
- virtual void SendSetBoolOption(PP_TCPSocketOption_Private name,
- bool value) = 0;
-
- protected:
- enum ConnectionState {
- // Before a connection is successfully established (including a connect
- // request is pending or a previous connect request failed).
- BEFORE_CONNECT,
- // A connection has been successfully established (including a request of
- // initiating SSL is pending).
- CONNECTED,
- // An SSL connection has been successfully established.
- SSL_CONNECTED,
- // The connection has been ended.
- DISCONNECTED
- };
-
- void Init(uint32 socket_id);
- bool IsConnected() const;
- void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback);
-
- ResourceObjectType resource_type_;
-
- uint32 socket_id_;
- ConnectionState connection_state_;
-
- scoped_refptr<TrackedCallback> connect_callback_;
- scoped_refptr<TrackedCallback> ssl_handshake_callback_;
- scoped_refptr<TrackedCallback> read_callback_;
- scoped_refptr<TrackedCallback> write_callback_;
- scoped_refptr<TrackedCallback> set_option_callback_;
-
- char* read_buffer_;
- int32_t bytes_to_read_;
-
- PP_NetAddress_Private local_addr_;
- PP_NetAddress_Private remote_addr_;
-
- scoped_refptr<PPB_X509Certificate_Private_Shared> server_certificate_;
-
- std::vector<std::vector<char> > trusted_certificates_;
- std::vector<std::vector<char> > untrusted_certificates_;
+ // TCPSocketShared implementation.
+ virtual Resource* GetOwnerResource() OVERRIDE;
+ private:
DISALLOW_COPY_AND_ASSIGN(TCPSocketPrivateImpl);
};
diff --git a/ppapi/shared_impl/resource.h b/ppapi/shared_impl/resource.h
index f327388..05b3d51 100644
--- a/ppapi/shared_impl/resource.h
+++ b/ppapi/shared_impl/resource.h
@@ -63,6 +63,7 @@
F(PPB_TrueTypeFont_API) \
F(PPB_TrueTypeFont_Singleton_API) \
F(PPB_TCPServerSocket_Private_API) \
+ F(PPB_TCPSocket_API) \
F(PPB_TCPSocket_Private_API) \
F(PPB_UDPSocket_Private_API) \
F(PPB_URLLoader_API) \
diff --git a/ppapi/shared_impl/tcp_socket_shared.cc b/ppapi/shared_impl/tcp_socket_shared.cc
new file mode 100644
index 0000000..8799c49
--- /dev/null
+++ b/ppapi/shared_impl/tcp_socket_shared.cc
@@ -0,0 +1,339 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/shared_impl/tcp_socket_shared.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h"
+#include "ppapi/shared_impl/var_tracker.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_x509_certificate_private_api.h"
+
+namespace ppapi {
+
+const int32_t TCPSocketShared::kMaxReadSize = 1024 * 1024;
+const int32_t TCPSocketShared::kMaxWriteSize = 1024 * 1024;
+
+TCPSocketShared::TCPSocketShared(ResourceObjectType resource_type,
+ uint32 socket_id)
+ : resource_type_(resource_type) {
+ Init(socket_id);
+}
+
+TCPSocketShared::~TCPSocketShared() {
+}
+
+void TCPSocketShared::OnConnectCompleted(
+ bool succeeded,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr) {
+ if (connection_state_ != BEFORE_CONNECT ||
+ !TrackedCallback::IsPending(connect_callback_)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ local_addr_ = local_addr;
+ remote_addr_ = remote_addr;
+ connection_state_ = CONNECTED;
+ }
+ connect_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
+}
+
+void TCPSocketShared::OnSSLHandshakeCompleted(
+ bool succeeded,
+ const PPB_X509Certificate_Fields& certificate_fields) {
+ if (connection_state_ != CONNECTED ||
+ !TrackedCallback::IsPending(ssl_handshake_callback_)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ connection_state_ = SSL_CONNECTED;
+ server_certificate_ = new PPB_X509Certificate_Private_Shared(
+ resource_type_,
+ GetOwnerResource()->pp_instance(),
+ certificate_fields);
+ ssl_handshake_callback_->Run(PP_OK);
+ } else {
+ // The resource might be released in the callback so we need to hold
+ // a reference so we can Disconnect() first.
+ GetOwnerResource()->AddRef();
+ ssl_handshake_callback_->Run(PP_ERROR_FAILED);
+ DisconnectImpl();
+ GetOwnerResource()->Release();
+ }
+}
+
+void TCPSocketShared::OnReadCompleted(bool succeeded,
+ const std::string& data) {
+ if (!TrackedCallback::IsPending(read_callback_) || !read_buffer_) {
+ NOTREACHED();
+ return;
+ }
+
+ if (succeeded) {
+ CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
+ if (!data.empty())
+ memcpy(read_buffer_, data.c_str(), data.size());
+ }
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+
+ read_callback_->Run(
+ succeeded ? static_cast<int32_t>(data.size()) :
+ static_cast<int32_t>(PP_ERROR_FAILED));
+}
+
+void TCPSocketShared::OnWriteCompleted(bool succeeded,
+ int32_t bytes_written) {
+ if (!TrackedCallback::IsPending(write_callback_) ||
+ (succeeded && bytes_written < 0)) {
+ NOTREACHED();
+ return;
+ }
+
+ write_callback_->Run(
+ succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED));
+}
+
+void TCPSocketShared::OnSetOptionCompleted(bool succeeded) {
+ if (!TrackedCallback::IsPending(set_option_callback_)) {
+ NOTREACHED();
+ return;
+ }
+
+ set_option_callback_->Run(succeeded ? PP_OK : PP_ERROR_FAILED);
+}
+
+int32_t TCPSocketShared::ConnectImpl(const char* host,
+ uint16_t port,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!host)
+ return PP_ERROR_BADARGUMENT;
+ if (connection_state_ != BEFORE_CONNECT)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(connect_callback_))
+ return PP_ERROR_INPROGRESS; // Can only have one pending request.
+
+ connect_callback_ = callback;
+ // Send the request, the browser will call us back via ConnectACK.
+ SendConnect(host, port);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TCPSocketShared::ConnectWithNetAddressImpl(
+ const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!addr)
+ return PP_ERROR_BADARGUMENT;
+ if (connection_state_ != BEFORE_CONNECT)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(connect_callback_))
+ return PP_ERROR_INPROGRESS; // Can only have one pending request.
+
+ connect_callback_ = callback;
+ // Send the request, the browser will call us back via ConnectACK.
+ SendConnectWithNetAddress(*addr);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Bool TCPSocketShared::GetLocalAddressImpl(
+ PP_NetAddress_Private* local_addr) {
+ if (!IsConnected() || !local_addr)
+ return PP_FALSE;
+
+ *local_addr = local_addr_;
+ return PP_TRUE;
+}
+
+PP_Bool TCPSocketShared::GetRemoteAddressImpl(
+ PP_NetAddress_Private* remote_addr) {
+ if (!IsConnected() || !remote_addr)
+ return PP_FALSE;
+
+ *remote_addr = remote_addr_;
+ return PP_TRUE;
+}
+
+int32_t TCPSocketShared::SSLHandshakeImpl(
+ const char* server_name,
+ uint16_t server_port,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!server_name)
+ return PP_ERROR_BADARGUMENT;
+
+ if (connection_state_ != CONNECTED)
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(ssl_handshake_callback_) ||
+ TrackedCallback::IsPending(read_callback_) ||
+ TrackedCallback::IsPending(write_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ ssl_handshake_callback_ = callback;
+
+ // Send the request, the browser will call us back via SSLHandshakeACK.
+ SendSSLHandshake(server_name, server_port, trusted_certificates_,
+ untrusted_certificates_);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+PP_Resource TCPSocketShared::GetServerCertificateImpl() {
+ if (!server_certificate_.get())
+ return 0;
+ return server_certificate_->GetReference();
+}
+
+PP_Bool TCPSocketShared::AddChainBuildingCertificateImpl(
+ PP_Resource certificate,
+ PP_Bool trusted) {
+ // TODO(raymes): The plumbing for this functionality is implemented but the
+ // certificates aren't yet used for the connection, so just return false for
+ // now.
+ return PP_FALSE;
+
+ thunk::EnterResourceNoLock<thunk::PPB_X509Certificate_Private_API>
+ enter_cert(certificate, true);
+ if (enter_cert.failed())
+ return PP_FALSE;
+
+ PP_Var der_var = enter_cert.object()->GetField(
+ PP_X509CERTIFICATE_PRIVATE_RAW);
+ ArrayBufferVar* der_array_buffer = ArrayBufferVar::FromPPVar(der_var);
+ PP_Bool success = PP_FALSE;
+ if (der_array_buffer) {
+ const char* der_bytes = static_cast<const char*>(der_array_buffer->Map());
+ uint32_t der_length = der_array_buffer->ByteLength();
+ std::vector<char> der(der_bytes, der_bytes + der_length);
+ if (PP_ToBool(trusted))
+ trusted_certificates_.push_back(der);
+ else
+ untrusted_certificates_.push_back(der);
+ success = PP_TRUE;
+ }
+ PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(der_var);
+ return success;
+}
+
+int32_t TCPSocketShared::ReadImpl(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!buffer || bytes_to_read <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!IsConnected())
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(read_callback_) ||
+ TrackedCallback::IsPending(ssl_handshake_callback_))
+ return PP_ERROR_INPROGRESS;
+ read_buffer_ = buffer;
+ bytes_to_read_ = std::min(bytes_to_read, kMaxReadSize);
+ read_callback_ = callback;
+
+ // Send the request, the browser will call us back via ReadACK.
+ SendRead(bytes_to_read_);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t TCPSocketShared::WriteImpl(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!buffer || bytes_to_write <= 0)
+ return PP_ERROR_BADARGUMENT;
+
+ if (!IsConnected())
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(write_callback_) ||
+ TrackedCallback::IsPending(ssl_handshake_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ if (bytes_to_write > kMaxWriteSize)
+ bytes_to_write = kMaxWriteSize;
+
+ write_callback_ = callback;
+
+ // Send the request, the browser will call us back via WriteACK.
+ SendWrite(std::string(buffer, bytes_to_write));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void TCPSocketShared::DisconnectImpl() {
+ if (connection_state_ == DISCONNECTED)
+ return;
+
+ connection_state_ = DISCONNECTED;
+
+ SendDisconnect();
+ socket_id_ = 0;
+
+ PostAbortIfNecessary(&connect_callback_);
+ PostAbortIfNecessary(&ssl_handshake_callback_);
+ PostAbortIfNecessary(&read_callback_);
+ PostAbortIfNecessary(&write_callback_);
+ PostAbortIfNecessary(&set_option_callback_);
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+ server_certificate_ = NULL;
+}
+
+int32_t TCPSocketShared::SetOptionImpl(
+ PP_TCPSocketOption_Private name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) {
+ if (!IsConnected())
+ return PP_ERROR_FAILED;
+ if (TrackedCallback::IsPending(set_option_callback_))
+ return PP_ERROR_INPROGRESS;
+
+ set_option_callback_ = callback;
+
+ switch (name) {
+ case PP_TCPSOCKETOPTION_NO_DELAY:
+ if (value.type != PP_VARTYPE_BOOL)
+ return PP_ERROR_BADARGUMENT;
+ SendSetBoolOption(name, PP_ToBool(value.value.as_bool));
+ return PP_OK_COMPLETIONPENDING;
+ default:
+ return PP_ERROR_BADARGUMENT;
+ }
+}
+
+void TCPSocketShared::Init(uint32 socket_id) {
+ DCHECK(socket_id != 0);
+ socket_id_ = socket_id;
+ connection_state_ = BEFORE_CONNECT;
+ read_buffer_ = NULL;
+ bytes_to_read_ = -1;
+
+ local_addr_.size = 0;
+ memset(local_addr_.data, 0,
+ arraysize(local_addr_.data) * sizeof(*local_addr_.data));
+ remote_addr_.size = 0;
+ memset(remote_addr_.data, 0,
+ arraysize(remote_addr_.data) * sizeof(*remote_addr_.data));
+}
+
+bool TCPSocketShared::IsConnected() const {
+ return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED;
+}
+
+void TCPSocketShared::PostAbortIfNecessary(
+ scoped_refptr<TrackedCallback>* callback) {
+ if (TrackedCallback::IsPending(*callback))
+ (*callback)->PostAbort();
+}
+
+} // namespace ppapi
diff --git a/ppapi/shared_impl/tcp_socket_shared.h b/ppapi/shared_impl/tcp_socket_shared.h
new file mode 100644
index 0000000..bd5e56b
--- /dev/null
+++ b/ppapi/shared_impl/tcp_socket_shared.h
@@ -0,0 +1,133 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_SHARED_IMPL_TCP_SOCKET_SHARED_H_
+#define PPAPI_SHARED_IMPL_TCP_SOCKET_SHARED_H_
+
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "ppapi/c/private/ppb_tcp_socket_private.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+
+namespace ppapi {
+
+class PPB_X509Certificate_Fields;
+class PPB_X509Certificate_Private_Shared;
+
+// This class provides the shared implementation for both PPB_TCPSocket and
+// PPB_TCPSocket_Private.
+class PPAPI_SHARED_EXPORT TCPSocketShared {
+ public:
+ // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read
+ // message is allowed to request.
+ static const int32_t kMaxReadSize;
+ // The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Write
+ // message is allowed to carry.
+ static const int32_t kMaxWriteSize;
+
+ // Notifications on operations completion.
+ void OnConnectCompleted(bool succeeded,
+ const PP_NetAddress_Private& local_addr,
+ const PP_NetAddress_Private& remote_addr);
+ void OnSSLHandshakeCompleted(
+ bool succeeded,
+ const PPB_X509Certificate_Fields& certificate_fields);
+ void OnReadCompleted(bool succeeded, const std::string& data);
+ void OnWriteCompleted(bool succeeded, int32_t bytes_written);
+ void OnSetOptionCompleted(bool succeeded);
+
+ // Send functions that need to be implemented differently for the
+ // proxied and non-proxied derived classes.
+ virtual void SendConnect(const std::string& host, uint16_t port) = 0;
+ virtual void SendConnectWithNetAddress(const PP_NetAddress_Private& addr) = 0;
+ virtual void SendSSLHandshake(
+ const std::string& server_name,
+ uint16_t server_port,
+ const std::vector<std::vector<char> >& trusted_certs,
+ const std::vector<std::vector<char> >& untrusted_certs) = 0;
+ virtual void SendRead(int32_t bytes_to_read) = 0;
+ virtual void SendWrite(const std::string& buffer) = 0;
+ virtual void SendDisconnect() = 0;
+ virtual void SendSetBoolOption(PP_TCPSocketOption_Private name,
+ bool value) = 0;
+
+ virtual Resource* GetOwnerResource() = 0;
+
+ protected:
+ enum ConnectionState {
+ // Before a connection is successfully established (including a connect
+ // request is pending or a previous connect request failed).
+ BEFORE_CONNECT,
+ // A connection has been successfully established (including a request of
+ // initiating SSL is pending).
+ CONNECTED,
+ // An SSL connection has been successfully established.
+ SSL_CONNECTED,
+ // The connection has been ended.
+ DISCONNECTED
+ };
+
+ TCPSocketShared(ResourceObjectType resource_type, uint32 socket_id);
+ virtual ~TCPSocketShared();
+
+ int32_t ConnectImpl(const char* host,
+ uint16_t port,
+ scoped_refptr<TrackedCallback> callback);
+ int32_t ConnectWithNetAddressImpl(const PP_NetAddress_Private* addr,
+ scoped_refptr<TrackedCallback> callback);
+ PP_Bool GetLocalAddressImpl(PP_NetAddress_Private* local_addr);
+ PP_Bool GetRemoteAddressImpl(PP_NetAddress_Private* remote_addr);
+ int32_t SSLHandshakeImpl(const char* server_name,
+ uint16_t server_port,
+ scoped_refptr<TrackedCallback> callback);
+ PP_Resource GetServerCertificateImpl();
+ PP_Bool AddChainBuildingCertificateImpl(PP_Resource certificate,
+ PP_Bool trusted);
+ int32_t ReadImpl(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback);
+ int32_t WriteImpl(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback);
+ void DisconnectImpl();
+ int32_t SetOptionImpl(PP_TCPSocketOption_Private name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback);
+
+ void Init(uint32 socket_id);
+ bool IsConnected() const;
+ void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback);
+
+ ResourceObjectType resource_type_;
+
+ uint32 socket_id_;
+ ConnectionState connection_state_;
+
+ scoped_refptr<TrackedCallback> connect_callback_;
+ scoped_refptr<TrackedCallback> ssl_handshake_callback_;
+ scoped_refptr<TrackedCallback> read_callback_;
+ scoped_refptr<TrackedCallback> write_callback_;
+ scoped_refptr<TrackedCallback> set_option_callback_;
+
+ char* read_buffer_;
+ int32_t bytes_to_read_;
+
+ PP_NetAddress_Private local_addr_;
+ PP_NetAddress_Private remote_addr_;
+
+ scoped_refptr<PPB_X509Certificate_Private_Shared> server_certificate_;
+
+ std::vector<std::vector<char> > trusted_certificates_;
+ std::vector<std::vector<char> > untrusted_certificates_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TCPSocketShared);
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_TCP_SOCKET_SHARED_H_
diff --git a/ppapi/tests/all_c_includes.h b/ppapi/tests/all_c_includes.h
index d550c21..4a8ae13 100644
--- a/ppapi/tests/all_c_includes.h
+++ b/ppapi/tests/all_c_includes.h
@@ -26,6 +26,7 @@
#include "ppapi/c/dev/ppb_printing_dev.h"
#include "ppapi/c/dev/ppb_resource_array_dev.h"
#include "ppapi/c/dev/ppb_scrollbar_dev.h"
+#include "ppapi/c/dev/ppb_tcp_socket_dev.h"
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/dev/ppb_text_input_dev.h"
#include "ppapi/c/dev/ppb_trace_event_dev.h"
diff --git a/ppapi/tests/all_cpp_includes.h b/ppapi/tests/all_cpp_includes.h
index 45fddf2..37a4100 100644
--- a/ppapi/tests/all_cpp_includes.h
+++ b/ppapi/tests/all_cpp_includes.h
@@ -26,6 +26,7 @@
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
#include "ppapi/cpp/dev/scrollbar_dev.h"
#include "ppapi/cpp/dev/selection_dev.h"
+#include "ppapi/cpp/dev/tcp_socket_dev.h"
#include "ppapi/cpp/dev/text_input_dev.h"
#include "ppapi/cpp/dev/url_util_dev.h"
#include "ppapi/cpp/dev/var_array_dev.h"
diff --git a/ppapi/tests/test_tcp_socket.cc b/ppapi/tests/test_tcp_socket.cc
new file mode 100644
index 0000000..7a14fe7
--- /dev/null
+++ b/ppapi/tests/test_tcp_socket.cc
@@ -0,0 +1,160 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/tests/test_tcp_socket.h"
+
+#include "ppapi/cpp/dev/tcp_socket_dev.h"
+#include "ppapi/tests/test_utils.h"
+#include "ppapi/tests/testing_instance.h"
+
+namespace {
+
+// Validates the first line of an HTTP response.
+bool ValidateHttpResponse(const std::string& s) {
+ // Just check that it begins with "HTTP/" and ends with a "\r\n".
+ return s.size() >= 5 &&
+ s.substr(0, 5) == "HTTP/" &&
+ s.substr(s.size() - 2) == "\r\n";
+}
+
+} // namespace
+
+REGISTER_TEST_CASE(TCPSocket);
+
+TestTCPSocket::TestTCPSocket(TestingInstance* instance) : TestCase(instance) {
+}
+
+bool TestTCPSocket::Init() {
+ if (!pp::TCPSocket_Dev::IsAvailable())
+ return false;
+
+ // We need something to connect to, so we connect to the HTTP server whence we
+ // came. Grab the host and port.
+ if (!EnsureRunningOverHTTP())
+ return false;
+
+ std::string host;
+ uint16_t port = 0;
+ if (!GetLocalHostPort(instance_->pp_instance(), &host, &port))
+ return false;
+
+ if (!ResolveHost(instance_->pp_instance(), host, port, &addr_))
+ return false;
+
+ return true;
+}
+
+void TestTCPSocket::RunTests(const std::string& filter) {
+ RUN_CALLBACK_TEST(TestTCPSocket, Connect, filter);
+ RUN_CALLBACK_TEST(TestTCPSocket, ReadWrite, filter);
+ RUN_CALLBACK_TEST(TestTCPSocket, SetOption, filter);
+}
+
+std::string TestTCPSocket::TestConnect() {
+ pp::TCPSocket_Dev socket(instance_);
+ TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+
+ cb.WaitForResult(socket.Connect(addr_, cb.GetCallback()));
+ CHECK_CALLBACK_BEHAVIOR(cb);
+ ASSERT_EQ(PP_OK, cb.result());
+
+ pp::NetAddress_Dev local_addr, remote_addr;
+ local_addr = socket.GetLocalAddress();
+ remote_addr = socket.GetRemoteAddress();
+
+ ASSERT_NE(0, local_addr.pp_resource());
+ ASSERT_NE(0, remote_addr.pp_resource());
+ ASSERT_TRUE(EqualNetAddress(addr_, remote_addr));
+
+ socket.Close();
+
+ PASS();
+}
+
+std::string TestTCPSocket::TestReadWrite() {
+ pp::TCPSocket_Dev socket(instance_);
+ TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+
+ cb.WaitForResult(socket.Connect(addr_, cb.GetCallback()));
+ CHECK_CALLBACK_BEHAVIOR(cb);
+ ASSERT_EQ(PP_OK, cb.result());
+
+ ASSERT_EQ(PP_OK, WriteStringToSocket(&socket, "GET / HTTP/1.0\r\n\r\n"));
+
+ // Read up to the first \n and check that it looks like valid HTTP response.
+ std::string s;
+ ASSERT_EQ(PP_OK, ReadFirstLineFromSocket(&socket, &s));
+ ASSERT_TRUE(ValidateHttpResponse(s));
+
+ PASS();
+}
+
+std::string TestTCPSocket::TestSetOption() {
+ pp::TCPSocket_Dev socket(instance_);
+ TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+
+ cb.WaitForResult(
+ socket.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY, true, cb.GetCallback()));
+ CHECK_CALLBACK_BEHAVIOR(cb);
+ ASSERT_EQ(PP_ERROR_FAILED, cb.result());
+
+ cb.WaitForResult(socket.Connect(addr_, cb.GetCallback()));
+ CHECK_CALLBACK_BEHAVIOR(cb);
+ ASSERT_EQ(PP_OK, cb.result());
+
+ cb.WaitForResult(
+ socket.SetOption(PP_TCPSOCKET_OPTION_NO_DELAY, true, cb.GetCallback()));
+ CHECK_CALLBACK_BEHAVIOR(cb);
+ ASSERT_EQ(PP_OK, cb.result());
+
+ PASS();
+}
+
+int32_t TestTCPSocket::ReadFirstLineFromSocket(pp::TCPSocket_Dev* socket,
+ std::string* s) {
+ char buffer[1000];
+
+ s->clear();
+ // Make sure we don't just hang if |Read()| spews.
+ while (s->size() < 10000) {
+ TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+ int32_t rv = socket->Read(buffer, sizeof(buffer), cb.GetCallback());
+ if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING)
+ return PP_ERROR_FAILED;
+ cb.WaitForResult(rv);
+ if (cb.result() < 0)
+ return cb.result();
+ if (cb.result() == 0)
+ return PP_ERROR_FAILED; // Didn't get a \n-terminated line.
+ s->reserve(s->size() + cb.result());
+ for (int32_t i = 0; i < cb.result(); i++) {
+ s->push_back(buffer[i]);
+ if (buffer[i] == '\n')
+ return PP_OK;
+ }
+ }
+ return PP_ERROR_FAILED;
+}
+
+int32_t TestTCPSocket::WriteStringToSocket(pp::TCPSocket_Dev* socket,
+ const std::string& s) {
+ const char* buffer = s.data();
+ size_t written = 0;
+ while (written < s.size()) {
+ TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+ int32_t rv = socket->Write(buffer + written, s.size() - written,
+ cb.GetCallback());
+ if (callback_type() == PP_REQUIRED && rv != PP_OK_COMPLETIONPENDING)
+ return PP_ERROR_FAILED;
+ cb.WaitForResult(rv);
+ if (cb.result() < 0)
+ return cb.result();
+ if (cb.result() == 0)
+ return PP_ERROR_FAILED;
+ written += cb.result();
+ }
+ if (written != s.size())
+ return PP_ERROR_FAILED;
+ return PP_OK;
+}
diff --git a/ppapi/tests/test_tcp_socket.h b/ppapi/tests/test_tcp_socket.h
new file mode 100644
index 0000000..0ff7e33
--- /dev/null
+++ b/ppapi/tests/test_tcp_socket.h
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PAPPI_TESTS_TEST_TCP_SOCKET_H_
+#define PAPPI_TESTS_TEST_TCP_SOCKET_H_
+
+#include <string>
+
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/cpp/dev/net_address_dev.h"
+#include "ppapi/tests/test_case.h"
+
+namespace pp {
+class TCPSocket_Dev;
+}
+
+class TestTCPSocket: public TestCase {
+ public:
+ explicit TestTCPSocket(TestingInstance* instance);
+
+ // TestCase implementation.
+ virtual bool Init();
+ virtual void RunTests(const std::string& filter);
+
+ private:
+ std::string TestConnect();
+ std::string TestReadWrite();
+ std::string TestSetOption();
+
+ int32_t ReadFirstLineFromSocket(pp::TCPSocket_Dev* socket, std::string* s);
+ int32_t WriteStringToSocket(pp::TCPSocket_Dev* socket, const std::string& s);
+
+ pp::NetAddress_Dev addr_;
+};
+
+#endif // PAPPI_TESTS_TEST_TCP_SOCKET_H_
diff --git a/ppapi/tests/test_utils.cc b/ppapi/tests/test_utils.cc
index 86a9bc1..509d6ff 100644
--- a/ppapi/tests/test_utils.cc
+++ b/ppapi/tests/test_utils.cc
@@ -6,6 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#if defined(_MSC_VER)
#include <windows.h>
#else
@@ -13,7 +14,11 @@
#endif
#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/dev/net_address_dev.h"
+#include "ppapi/cpp/instance_handle.h"
#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/private/host_resolver_private.h"
+#include "ppapi/cpp/private/net_address_private.h"
#include "ppapi/cpp/var.h"
namespace {
@@ -98,6 +103,82 @@ uint16_t ConvertToNetEndian16(uint16_t x) {
return (x << 8) | (x >> 8);
}
+bool EqualNetAddress(const pp::NetAddress_Dev& addr1,
+ const pp::NetAddress_Dev& addr2) {
+ if (addr1.GetFamily() == PP_NETADDRESS_FAMILY_UNSPECIFIED ||
+ addr2.GetFamily() == PP_NETADDRESS_FAMILY_UNSPECIFIED) {
+ return false;
+ }
+
+ if (addr1.GetFamily() == PP_NETADDRESS_FAMILY_IPV4) {
+ PP_NetAddress_IPv4_Dev ipv4_addr1, ipv4_addr2;
+ if (!addr1.DescribeAsIPv4Address(&ipv4_addr1) ||
+ !addr2.DescribeAsIPv4Address(&ipv4_addr2)) {
+ return false;
+ }
+
+ return ipv4_addr1.port == ipv4_addr2.port &&
+ !memcmp(ipv4_addr1.addr, ipv4_addr2.addr, sizeof(ipv4_addr1.addr));
+ } else {
+ PP_NetAddress_IPv6_Dev ipv6_addr1, ipv6_addr2;
+ if (!addr1.DescribeAsIPv6Address(&ipv6_addr1) ||
+ !addr2.DescribeAsIPv6Address(&ipv6_addr2)) {
+ return false;
+ }
+
+ return ipv6_addr1.port == ipv6_addr2.port &&
+ !memcmp(ipv6_addr1.addr, ipv6_addr2.addr, sizeof(ipv6_addr1.addr));
+ }
+}
+
+bool ResolveHost(PP_Instance instance,
+ const std::string& host,
+ uint16_t port,
+ pp::NetAddress_Dev* addr) {
+ // TODO(yzshen): Change to use the public host resolver once it is supported.
+ pp::InstanceHandle instance_handle(instance);
+ pp::HostResolverPrivate host_resolver(instance_handle);
+ PP_HostResolver_Private_Hint hint = { PP_NETADDRESSFAMILY_UNSPECIFIED, 0 };
+
+ TestCompletionCallback callback(instance);
+ callback.WaitForResult(
+ host_resolver.Resolve(host, port, hint, callback.GetCallback()));
+
+ PP_NetAddress_Private addr_private;
+ if (callback.result() != PP_OK || host_resolver.GetSize() == 0 ||
+ !host_resolver.GetNetAddress(0, &addr_private)) {
+ return false;
+ }
+
+ switch (pp::NetAddressPrivate::GetFamily(addr_private)) {
+ case PP_NETADDRESSFAMILY_IPV4: {
+ PP_NetAddress_IPv4_Dev ipv4_addr;
+ ipv4_addr.port = ConvertToNetEndian16(
+ pp::NetAddressPrivate::GetPort(addr_private));
+ if (!pp::NetAddressPrivate::GetAddress(addr_private, ipv4_addr.addr,
+ sizeof(ipv4_addr.addr))) {
+ return false;
+ }
+ *addr = pp::NetAddress_Dev(instance_handle, ipv4_addr);
+ return true;
+ }
+ case PP_NETADDRESSFAMILY_IPV6: {
+ PP_NetAddress_IPv6_Dev ipv6_addr;
+ ipv6_addr.port = ConvertToNetEndian16(
+ pp::NetAddressPrivate::GetPort(addr_private));
+ if (!pp::NetAddressPrivate::GetAddress(addr_private, ipv6_addr.addr,
+ sizeof(ipv6_addr.addr))) {
+ return false;
+ }
+ *addr = pp::NetAddress_Dev(instance_handle, ipv6_addr);
+ return true;
+ }
+ default: {
+ return false;
+ }
+ }
+}
+
void NestedEvent::Wait() {
PP_DCHECK(pp::Module::Get()->core()->IsMainThread());
// Don't allow nesting more than once; it doesn't work with the code as-is,
diff --git a/ppapi/tests/test_utils.h b/ppapi/tests/test_utils.h
index 0410018..04aa452 100644
--- a/ppapi/tests/test_utils.h
+++ b/ppapi/tests/test_utils.h
@@ -14,6 +14,10 @@
#include "ppapi/cpp/message_loop.h"
#include "ppapi/utility/completion_callback_factory.h"
+namespace pp {
+class NetAddress_Dev;
+}
+
// Timeout to wait for some action to complete.
extern const int kActionTimeoutMs;
@@ -24,6 +28,13 @@ bool GetLocalHostPort(PP_Instance instance, std::string* host, uint16_t* port);
uint16_t ConvertFromNetEndian16(uint16_t x);
uint16_t ConvertToNetEndian16(uint16_t x);
+bool EqualNetAddress(const pp::NetAddress_Dev& addr1,
+ const pp::NetAddress_Dev& addr2);
+// Only returns the first address if there are more than one available.
+bool ResolveHost(PP_Instance instance,
+ const std::string& host,
+ uint16_t port,
+ pp::NetAddress_Dev* addr);
// NestedEvent allows you to run a nested MessageLoop and wait for a particular
// event to complete. For example, you can use it to wait for a callback on a
diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h
index 1628e87..e953811 100644
--- a/ppapi/thunk/interfaces_ppb_public_dev.h
+++ b/ppapi/thunk/interfaces_ppb_public_dev.h
@@ -7,6 +7,8 @@
#include "ppapi/thunk/interfaces_preamble.h"
+PROXIED_API(PPB_TCPSocket)
+
// Map the old dev console interface to the stable one (which is the same) to
// keep Flash, etc. working.
PROXIED_IFACE(PPB_Instance, "PPB_Console(Dev);0.1", PPB_Console_1_0)
@@ -34,6 +36,8 @@ PROXIED_IFACE(NoAPIName, PPB_PRINTING_DEV_INTERFACE_0_7,
PPB_Printing_Dev_0_7)
PROXIED_IFACE(NoAPIName, PPB_RESOURCEARRAY_DEV_INTERFACE_0_1,
PPB_ResourceArray_Dev_0_1)
+PROXIED_IFACE(PPB_TCPSocket, PPB_TCPSOCKET_DEV_INTERFACE_0_1,
+ PPB_TCPSocket_Dev_0_1)
PROXIED_IFACE(PPB_Instance, PPB_TEXTINPUT_DEV_INTERFACE_0_2,
PPB_TextInput_Dev_0_2)
PROXIED_IFACE(NoAPIName, PPB_TRUETYPEFONT_DEV_INTERFACE_0_1,
diff --git a/ppapi/thunk/ppb_tcp_socket_api.h b/ppapi/thunk/ppb_tcp_socket_api.h
new file mode 100644
index 0000000..1b94a83
--- /dev/null
+++ b/ppapi/thunk/ppb_tcp_socket_api.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_THUNK_PPB_TCP_SOCKET_API_H_
+#define PPAPI_THUNK_PPB_TCP_SOCKET_API_H_
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/c/dev/ppb_tcp_socket_dev.h"
+#include "ppapi/thunk/ppapi_thunk_export.h"
+
+namespace ppapi {
+
+class TrackedCallback;
+
+namespace thunk {
+
+class PPAPI_THUNK_EXPORT PPB_TCPSocket_API {
+ public:
+ virtual ~PPB_TCPSocket_API() {}
+
+ virtual int32_t Connect(PP_Resource addr,
+ scoped_refptr<TrackedCallback> callback) = 0;
+ virtual PP_Resource GetLocalAddress() = 0;
+ virtual PP_Resource GetRemoteAddress() = 0;
+ virtual int32_t Read(char* buffer,
+ int32_t bytes_to_read,
+ scoped_refptr<TrackedCallback> callback) = 0;
+ virtual int32_t Write(const char* buffer,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) = 0;
+ virtual void Close() = 0;
+ virtual int32_t SetOption(PP_TCPSocket_Option_Dev name,
+ const PP_Var& value,
+ scoped_refptr<TrackedCallback> callback) = 0;
+};
+
+} // namespace thunk
+} // namespace ppapi
+
+#endif // PPAPI_THUNK_PPB_TCP_SOCKET_API_H_
diff --git a/ppapi/thunk/ppb_tcp_socket_dev_thunk.cc b/ppapi/thunk/ppb_tcp_socket_dev_thunk.cc
new file mode 100644
index 0000000..43a1968
--- /dev/null
+++ b/ppapi/thunk/ppb_tcp_socket_dev_thunk.cc
@@ -0,0 +1,128 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// From dev/ppb_tcp_socket_dev.idl modified Wed Jun 05 23:11:18 2013.
+
+#include "ppapi/c/dev/ppb_tcp_socket_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_instance_api.h"
+#include "ppapi/thunk/ppb_tcp_socket_api.h"
+#include "ppapi/thunk/resource_creation_api.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace thunk {
+
+namespace {
+
+PP_Resource Create(PP_Instance instance) {
+ VLOG(4) << "PPB_TCPSocket_Dev::Create()";
+ EnterResourceCreation enter(instance);
+ if (enter.failed())
+ return 0;
+ return enter.functions()->CreateTCPSocket(instance);
+}
+
+PP_Bool IsTCPSocket(PP_Resource resource) {
+ VLOG(4) << "PPB_TCPSocket_Dev::IsTCPSocket()";
+ EnterResource<PPB_TCPSocket_API> enter(resource, false);
+ return PP_FromBool(enter.succeeded());
+}
+
+int32_t Connect(PP_Resource tcp_socket,
+ PP_Resource addr,
+ struct PP_CompletionCallback callback) {
+ VLOG(4) << "PPB_TCPSocket_Dev::Connect()";
+ EnterResource<PPB_TCPSocket_API> enter(tcp_socket, callback, true);
+ if (enter.failed())
+ return enter.retval();
+ return enter.SetResult(enter.object()->Connect(addr, enter.callback()));
+}
+
+PP_Resource GetLocalAddress(PP_Resource tcp_socket) {
+ VLOG(4) << "PPB_TCPSocket_Dev::GetLocalAddress()";
+ EnterResource<PPB_TCPSocket_API> enter(tcp_socket, true);
+ if (enter.failed())
+ return 0;
+ return enter.object()->GetLocalAddress();
+}
+
+PP_Resource GetRemoteAddress(PP_Resource tcp_socket) {
+ VLOG(4) << "PPB_TCPSocket_Dev::GetRemoteAddress()";
+ EnterResource<PPB_TCPSocket_API> enter(tcp_socket, true);
+ if (enter.failed())
+ return 0;
+ return enter.object()->GetRemoteAddress();
+}
+
+int32_t Read(PP_Resource tcp_socket,
+ char* buffer,
+ int32_t bytes_to_read,
+ struct PP_CompletionCallback callback) {
+ VLOG(4) << "PPB_TCPSocket_Dev::Read()";
+ EnterResource<PPB_TCPSocket_API> enter(tcp_socket, callback, true);
+ if (enter.failed())
+ return enter.retval();
+ return enter.SetResult(enter.object()->Read(buffer,
+ bytes_to_read,
+ enter.callback()));
+}
+
+int32_t Write(PP_Resource tcp_socket,
+ const char* buffer,
+ int32_t bytes_to_write,
+ struct PP_CompletionCallback callback) {
+ VLOG(4) << "PPB_TCPSocket_Dev::Write()";
+ EnterResource<PPB_TCPSocket_API> enter(tcp_socket, callback, true);
+ if (enter.failed())
+ return enter.retval();
+ return enter.SetResult(enter.object()->Write(buffer,
+ bytes_to_write,
+ enter.callback()));
+}
+
+void Close(PP_Resource tcp_socket) {
+ VLOG(4) << "PPB_TCPSocket_Dev::Close()";
+ EnterResource<PPB_TCPSocket_API> enter(tcp_socket, true);
+ if (enter.failed())
+ return;
+ enter.object()->Close();
+}
+
+int32_t SetOption(PP_Resource tcp_socket,
+ PP_TCPSocket_Option_Dev name,
+ struct PP_Var value,
+ struct PP_CompletionCallback callback) {
+ VLOG(4) << "PPB_TCPSocket_Dev::SetOption()";
+ EnterResource<PPB_TCPSocket_API> enter(tcp_socket, callback, true);
+ if (enter.failed())
+ return enter.retval();
+ return enter.SetResult(enter.object()->SetOption(name,
+ value,
+ enter.callback()));
+}
+
+const PPB_TCPSocket_Dev_0_1 g_ppb_tcpsocket_dev_thunk_0_1 = {
+ &Create,
+ &IsTCPSocket,
+ &Connect,
+ &GetLocalAddress,
+ &GetRemoteAddress,
+ &Read,
+ &Write,
+ &Close,
+ &SetOption
+};
+
+} // namespace
+
+const PPB_TCPSocket_Dev_0_1* GetPPB_TCPSocket_Dev_0_1_Thunk() {
+ return &g_ppb_tcpsocket_dev_thunk_0_1;
+}
+
+} // namespace thunk
+} // namespace ppapi
diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h
index 38b6d12..a760030 100644
--- a/ppapi/thunk/resource_creation_api.h
+++ b/ppapi/thunk/resource_creation_api.h
@@ -28,6 +28,7 @@ struct PP_FontDescription_Dev;
struct PP_BrowserFont_Trusted_Description;
struct PP_NetAddress_IPv4_Dev;
struct PP_NetAddress_IPv6_Dev;
+struct PP_NetAddress_Private;
struct PP_Size;
namespace ppapi {
@@ -141,12 +142,16 @@ class ResourceCreationAPI {
virtual PP_Resource CreateNetAddressFromIPv6Address(
PP_Instance instance,
const PP_NetAddress_IPv6_Dev* ipv6_addr) = 0;
+ virtual PP_Resource CreateNetAddressFromNetAddressPrivate(
+ PP_Instance instance,
+ const PP_NetAddress_Private& private_addr) = 0;
virtual PP_Resource CreateNetworkMonitor(
PP_Instance instance,
PPB_NetworkMonitor_Callback callback,
void* user_data) = 0;
virtual PP_Resource CreatePrinting(PP_Instance instance) = 0;
virtual PP_Resource CreateTCPServerSocketPrivate(PP_Instance instance) = 0;
+ virtual PP_Resource CreateTCPSocket(PP_Instance instace) = 0;
virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instace) = 0;
virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instace) = 0;
virtual PP_Resource CreateWebSocket(PP_Instance instance) = 0;