diff options
Diffstat (limited to 'ppapi')
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; |