diff options
author | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-13 22:43:39 +0000 |
---|---|---|
committer | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-13 22:43:39 +0000 |
commit | 31cb147366bde602adf20717c478ff54c09cb4c2 (patch) | |
tree | 94f7243da6e7ec64fa2594fb5c5a97863de406da | |
parent | dcab1bf3aa1029789765b5a74727ba0653460efc (diff) | |
download | chromium_src-31cb147366bde602adf20717c478ff54c09cb4c2.zip chromium_src-31cb147366bde602adf20717c478ff54c09cb4c2.tar.gz chromium_src-31cb147366bde602adf20717c478ff54c09cb4c2.tar.bz2 |
Introduce PPB_UDPSocket_Dev.
This change exposes the PPB_UDPSocket_Dev interface and makes it to share the same backend as PPB_UDPSocket_Private.
It doesn't include:
- apps permission check;
- UDP socket options that PPB_UDPSocket_Private doesn't support.
These will be implemented in separate CLs.
BUG=247225
TEST=newly added test_udp_socket.{h,cc}.
Review URL: https://chromiumcodereview.appspot.com/16282005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@206183 0039d316-1c4b-4281-b951-d872f2087c98
32 files changed, 1513 insertions, 238 deletions
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index 15853be..31dabe6 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc @@ -337,6 +337,46 @@ TEST_PPAPI_NACL_WITH_SSL_SERVER(TCPSocketPrivate) TEST_PPAPI_OUT_OF_PROCESS_WITH_SSL_SERVER(TCPSocketPrivateTrusted) TEST_PPAPI_IN_PROCESS_WITH_SSL_SERVER(TCPSocketPrivateTrusted) +// UDPSocket tests. +// UDPSocket_Broadcast is disabled for OSX because it requires root permissions +// on OSX 10.7+. +IN_PROC_BROWSER_TEST_F(OutOfProcessPPAPITest, UDPSocket) { + RunTestViaHTTP( + LIST_TEST(UDPSocket_ReadWrite) + LIST_TEST(UDPSocket_SetOption) +#if !defined(OS_MACOSX) + LIST_TEST(UDPSocket_Broadcast) +#endif + ); +} +IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, UDPSocket) { + RunTestViaHTTP( + LIST_TEST(UDPSocket_ReadWrite) + LIST_TEST(UDPSocket_SetOption) +#if !defined(OS_MACOSX) + LIST_TEST(UDPSocket_Broadcast) +#endif + ); +} +IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(UDPSocket)) { + RunTestViaHTTP( + LIST_TEST(UDPSocket_ReadWrite) + LIST_TEST(UDPSocket_SetOption) +#if !defined(OS_MACOSX) + LIST_TEST(UDPSocket_Broadcast) +#endif + ); +} +IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, UDPSocket) { + RunTestViaHTTP( + LIST_TEST(UDPSocket_ReadWrite) + LIST_TEST(UDPSocket_SetOption) +#if !defined(OS_MACOSX) + LIST_TEST(UDPSocket_Broadcast) +#endif + ); +} + // UDPSocketPrivate tests. // UDPSocketPrivate_Broadcast is disabled for OSX because it requires // root permissions on OSX 10.7+. diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list index 0f227be..b12f3de 100644 --- a/native_client_sdk/src/build_tools/sdk_files.list +++ b/native_client_sdk/src/build_tools/sdk_files.list @@ -288,6 +288,7 @@ 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 include/ppapi/c/dev/ppb_truetype_font_dev.h +include/ppapi/c/dev/ppb_udp_socket_dev.h include/ppapi/c/dev/ppb_url_util_dev.h include/ppapi/c/dev/ppb_var_array_dev.h include/ppapi/c/dev/ppb_var_deprecated.h @@ -389,6 +390,7 @@ 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/truetype_font_dev.h +include/ppapi/cpp/dev/udp_socket_dev.h include/ppapi/cpp/dev/url_util_dev.h include/ppapi/cpp/dev/var_array_dev.h include/ppapi/cpp/dev/var_dictionary_dev.h diff --git a/ppapi/api/dev/ppb_udp_socket_dev.idl b/ppapi/api/dev/ppb_udp_socket_dev.idl new file mode 100644 index 0000000..32ad30a --- /dev/null +++ b/ppapi/api/dev/ppb_udp_socket_dev.idl @@ -0,0 +1,107 @@ +/* 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_UDPSocket_Dev</code> interface. + * TODO(yzshen): Tidy up the document. + */ + +[generate_thunk] + +label Chrome { + M29 = 0.1 +}; + +[assert_size(4)] +enum PP_UDPSocket_Option_Dev { + // Allows the socket to share the local address to which it will be bound with + // other processes. Value's type should be PP_VARTYPE_BOOL. + PP_UDPSOCKET_OPTION_ADDRESS_REUSE = 0, + + // Allows sending and receiving packets to and from broadcast addresses. + // Value's type should be PP_VARTYPE_BOOL. + PP_UDPSOCKET_OPTION_BROADCAST = 1, + + // Specifies the total per-socket buffer space reserved for sends. 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 it will conform to it. + PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE = 2, + + // Specifies the total per-socket buffer space reserved for receives. 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 it will conform to it. + PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE = 3 +}; + +interface PPB_UDPSocket_Dev { + /** + * Creates a UDP socket resource. + */ + PP_Resource Create([in] PP_Instance instance); + + /** + * Determines if a given resource is a UDP socket. + */ + PP_Bool IsUDPSocket([in] PP_Resource resource); + + /** + * Binds to the address given by |addr|, which is a PPB_NetAddress_Dev + * resource. + */ + int32_t Bind([in] PP_Resource udp_socket, + [in] PP_Resource addr, + [in] PP_CompletionCallback callback); + + /** + * Returns the address that the socket has bound to, as a PPB_NetAddress_Dev + * resource. Bind must be called and succeed first. Returns 0 if Bind fails, + * or if Close has been called. + */ + PP_Resource GetBoundAddress([in] PP_Resource udp_socket); + + /** + * Performs a non-blocking recvfrom call on socket. + * Bind must be called first. |callback| is invoked when recvfrom reads data. + * |addr| will store a PPB_NetAddress_Dev resource on success. + */ + int32_t RecvFrom([in] PP_Resource udp_socket, + [out] str_t buffer, + [in] int32_t num_bytes, + [out] PP_Resource addr, + [in] PP_CompletionCallback callback); + + /** + * Performs a non-blocking sendto call on the socket. + * Bind must be called first. |addr| is a PPB_NetAddress_Dev resource holding + * the target address. |callback| is invoked when sendto completes. + */ + int32_t SendTo([in] PP_Resource udp_socket, + [in] str_t buffer, + [in] int32_t num_bytes, + [in] PP_Resource addr, + [in] PP_CompletionCallback callback); + + /** + * Cancels all pending reads and writes, and closes the socket. + */ + void Close([in] PP_Resource udp_socket); + + /** + * Sets a socket option to |udp_socket|. Should be called before Bind(). + * See the PP_UDPSocket_Option_Dev description for option names, value types + * and allowed values. + * Returns PP_OK on success. Otherwise, returns PP_ERROR_BADRESOURCE (if bad + * |udp_socket| provided), PP_ERROR_BADARGUMENT (if bad name/value/value's + * type provided) or PP_ERROR_FAILED in the case of internal errors. + */ + int32_t SetOption([in] PP_Resource udp_socket, + [in] PP_UDPSocket_Option_Dev name, + [in] PP_Var value, + [in] PP_CompletionCallback callback); +}; diff --git a/ppapi/c/dev/ppb_udp_socket_dev.h b/ppapi/c/dev/ppb_udp_socket_dev.h new file mode 100644 index 0000000..5aba580 --- /dev/null +++ b/ppapi/c/dev/ppb_udp_socket_dev.h @@ -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_udp_socket_dev.idl modified Thu Jun 13 09:38:45 2013. */ + +#ifndef PPAPI_C_DEV_PPB_UDP_SOCKET_DEV_H_ +#define PPAPI_C_DEV_PPB_UDP_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_UDPSOCKET_DEV_INTERFACE_0_1 "PPB_UDPSocket(Dev);0.1" +#define PPB_UDPSOCKET_DEV_INTERFACE PPB_UDPSOCKET_DEV_INTERFACE_0_1 + +/** + * @file + * This file defines the <code>PPB_UDPSocket_Dev</code> interface. + * TODO(yzshen): Tidy up the document. + */ + + +/** + * @addtogroup Enums + * @{ + */ +typedef enum { + /* Allows the socket to share the local address to which it will be bound with + * other processes. Value's type should be PP_VARTYPE_BOOL. */ + PP_UDPSOCKET_OPTION_ADDRESS_REUSE = 0, + /* Allows sending and receiving packets to and from broadcast addresses. + * Value's type should be PP_VARTYPE_BOOL. */ + PP_UDPSOCKET_OPTION_BROADCAST = 1, + /* Specifies the total per-socket buffer space reserved for sends. 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 it will conform to it. */ + PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE = 2, + /* Specifies the total per-socket buffer space reserved for receives. 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 it will conform to it. */ + PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE = 3 +} PP_UDPSocket_Option_Dev; +PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_UDPSocket_Option_Dev, 4); +/** + * @} + */ + +/** + * @addtogroup Interfaces + * @{ + */ +struct PPB_UDPSocket_Dev_0_1 { + /** + * Creates a UDP socket resource. + */ + PP_Resource (*Create)(PP_Instance instance); + /** + * Determines if a given resource is a UDP socket. + */ + PP_Bool (*IsUDPSocket)(PP_Resource resource); + /** + * Binds to the address given by |addr|, which is a PPB_NetAddress_Dev + * resource. + */ + int32_t (*Bind)(PP_Resource udp_socket, + PP_Resource addr, + struct PP_CompletionCallback callback); + /** + * Returns the address that the socket has bound to, as a PPB_NetAddress_Dev + * resource. Bind must be called and succeed first. Returns 0 if Bind fails, + * or if Close has been called. + */ + PP_Resource (*GetBoundAddress)(PP_Resource udp_socket); + /** + * Performs a non-blocking recvfrom call on socket. + * Bind must be called first. |callback| is invoked when recvfrom reads data. + * |addr| will store a PPB_NetAddress_Dev resource on success. + */ + int32_t (*RecvFrom)(PP_Resource udp_socket, + char* buffer, + int32_t num_bytes, + PP_Resource* addr, + struct PP_CompletionCallback callback); + /** + * Performs a non-blocking sendto call on the socket. + * Bind must be called first. |addr| is a PPB_NetAddress_Dev resource holding + * the target address. |callback| is invoked when sendto completes. + */ + int32_t (*SendTo)(PP_Resource udp_socket, + const char* buffer, + int32_t num_bytes, + PP_Resource addr, + struct PP_CompletionCallback callback); + /** + * Cancels all pending reads and writes, and closes the socket. + */ + void (*Close)(PP_Resource udp_socket); + /** + * Sets a socket option to |udp_socket|. Should be called before Bind(). + * See the PP_UDPSocket_Option_Dev description for option names, value types + * and allowed values. + * Returns PP_OK on success. Otherwise, returns PP_ERROR_BADRESOURCE (if bad + * |udp_socket| provided), PP_ERROR_BADARGUMENT (if bad name/value/value's + * type provided) or PP_ERROR_FAILED in the case of internal errors. + */ + int32_t (*SetOption)(PP_Resource udp_socket, + PP_UDPSocket_Option_Dev name, + struct PP_Var value, + struct PP_CompletionCallback callback); +}; + +typedef struct PPB_UDPSocket_Dev_0_1 PPB_UDPSocket_Dev; +/** + * @} + */ + +#endif /* PPAPI_C_DEV_PPB_UDP_SOCKET_DEV_H_ */ + diff --git a/ppapi/cpp/dev/udp_socket_dev.cc b/ppapi/cpp/dev/udp_socket_dev.cc new file mode 100644 index 0000000..dd8ffd0 --- /dev/null +++ b/ppapi/cpp/dev/udp_socket_dev.cc @@ -0,0 +1,111 @@ +// 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/udp_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" +#include "ppapi/cpp/var.h" + +namespace pp { + +namespace { + +template <> const char* interface_name<PPB_UDPSocket_Dev_0_1>() { + return PPB_UDPSOCKET_DEV_INTERFACE_0_1; +} + +} // namespace + +UDPSocket_Dev::UDPSocket_Dev() { +} + +UDPSocket_Dev::UDPSocket_Dev(const InstanceHandle& instance) { + if (has_interface<PPB_UDPSocket_Dev_0_1>()) { + PassRefFromConstructor(get_interface<PPB_UDPSocket_Dev_0_1>()->Create( + instance.pp_instance())); + } +} + +UDPSocket_Dev::UDPSocket_Dev(PassRef, PP_Resource resource) + : Resource(PASS_REF, resource) { +} + +UDPSocket_Dev::UDPSocket_Dev(const UDPSocket_Dev& other) : Resource(other) { +} + +UDPSocket_Dev::~UDPSocket_Dev() { +} + +UDPSocket_Dev& UDPSocket_Dev::operator=(const UDPSocket_Dev& other) { + Resource::operator=(other); + return *this; +} + +// static +bool UDPSocket_Dev::IsAvailable() { + return has_interface<PPB_UDPSocket_Dev_0_1>(); +} + +int32_t UDPSocket_Dev::Bind(const NetAddress_Dev& addr, + const CompletionCallback& callback) { + if (has_interface<PPB_UDPSocket_Dev_0_1>()) { + return get_interface<PPB_UDPSocket_Dev_0_1>()->Bind( + pp_resource(), addr.pp_resource(), callback.pp_completion_callback()); + } + return callback.MayForce(PP_ERROR_NOINTERFACE); +} + +NetAddress_Dev UDPSocket_Dev::GetBoundAddress() { + if (has_interface<PPB_UDPSocket_Dev_0_1>()) { + return NetAddress_Dev( + PASS_REF, + get_interface<PPB_UDPSocket_Dev_0_1>()->GetBoundAddress(pp_resource())); + } + return NetAddress_Dev(); +} + +int32_t UDPSocket_Dev::RecvFrom( + char* buffer, + int32_t num_bytes, + const CompletionCallbackWithOutput<NetAddress_Dev>& callback) { + if (has_interface<PPB_UDPSocket_Dev_0_1>()) { + return get_interface<PPB_UDPSocket_Dev_0_1>()->RecvFrom( + pp_resource(), buffer, num_bytes, callback.output(), + callback.pp_completion_callback()); + } + return callback.MayForce(PP_ERROR_NOINTERFACE); +} + +int32_t UDPSocket_Dev::SendTo(const char* buffer, + int32_t num_bytes, + const NetAddress_Dev& addr, + const CompletionCallback& callback) { + if (has_interface<PPB_UDPSocket_Dev_0_1>()) { + return get_interface<PPB_UDPSocket_Dev_0_1>()->SendTo( + pp_resource(), buffer, num_bytes, addr.pp_resource(), + callback.pp_completion_callback()); + } + return callback.MayForce(PP_ERROR_NOINTERFACE); +} + +void UDPSocket_Dev::Close() { + if (has_interface<PPB_UDPSocket_Dev_0_1>()) + return get_interface<PPB_UDPSocket_Dev_0_1>()->Close(pp_resource()); +} + +int32_t UDPSocket_Dev::SetOption(PP_UDPSocket_Option_Dev name, + const Var& value, + const CompletionCallback& callback) { + if (has_interface<PPB_UDPSocket_Dev_0_1>()) { + return get_interface<PPB_UDPSocket_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/udp_socket_dev.h b/ppapi/cpp/dev/udp_socket_dev.h new file mode 100644 index 0000000..9f46f0a --- /dev/null +++ b/ppapi/cpp/dev/udp_socket_dev.h @@ -0,0 +1,57 @@ +// 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_UDP_SOCKET_DEV_H_ +#define PPAPI_CPP_DEV_UDP_SOCKET_DEV_H_ + +#include "ppapi/c/dev/ppb_udp_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 Var; + +template <typename T> class CompletionCallbackWithOutput; + +class UDPSocket_Dev: public Resource { + public: + UDPSocket_Dev(); + + explicit UDPSocket_Dev(const InstanceHandle& instance); + + UDPSocket_Dev(PassRef, PP_Resource resource); + + UDPSocket_Dev(const UDPSocket_Dev& other); + + virtual ~UDPSocket_Dev(); + + UDPSocket_Dev& operator=(const UDPSocket_Dev& other); + + // Returns true if the required interface is available. + static bool IsAvailable(); + + int32_t Bind(const NetAddress_Dev& addr, + const CompletionCallback& callback); + NetAddress_Dev GetBoundAddress(); + int32_t RecvFrom( + char* buffer, + int32_t num_bytes, + const CompletionCallbackWithOutput<NetAddress_Dev>& callback); + int32_t SendTo(const char* buffer, + int32_t num_bytes, + const NetAddress_Dev& addr, + const CompletionCallback& callback); + void Close(); + int32_t SetOption(PP_UDPSocket_Option_Dev name, + const Var& value, + const CompletionCallback& callback); +}; + +} // namespace pp + +#endif // PPAPI_CPP_DEV_UDP_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 194925e..fcd0d8b 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 @@ -28,6 +28,7 @@ #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/c/dev/ppb_trace_event_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" +#include "ppapi/c/dev/ppb_udp_socket_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppb_var_array_dev.h" #include "ppapi/c/dev/ppb_var_dictionary_dev.h" @@ -209,6 +210,7 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TextInput_Dev_0_1; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TextInput_Dev_0_2; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Trace_Event_Dev_0_1; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TrueTypeFont_Dev_0_1; +static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_URLUtil_Dev_0_6; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VarArray_Dev_0_1; static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1; @@ -1949,6 +1951,50 @@ static int32_t Pnacl_M26_PPB_TrueTypeFont_Dev_GetTable(PP_Resource font, uint32_ /* End wrapper methods for PPB_TrueTypeFont_Dev_0_1 */ +/* Begin wrapper methods for PPB_UDPSocket_Dev_0_1 */ + +static PP_Resource Pnacl_M29_PPB_UDPSocket_Dev_Create(PP_Instance instance) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + return iface->Create(instance); +} + +static PP_Bool Pnacl_M29_PPB_UDPSocket_Dev_IsUDPSocket(PP_Resource resource) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + return iface->IsUDPSocket(resource); +} + +static int32_t Pnacl_M29_PPB_UDPSocket_Dev_Bind(PP_Resource udp_socket, PP_Resource addr, struct PP_CompletionCallback* callback) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + return iface->Bind(udp_socket, addr, *callback); +} + +static PP_Resource Pnacl_M29_PPB_UDPSocket_Dev_GetBoundAddress(PP_Resource udp_socket) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + return iface->GetBoundAddress(udp_socket); +} + +static int32_t Pnacl_M29_PPB_UDPSocket_Dev_RecvFrom(PP_Resource udp_socket, char* buffer, int32_t num_bytes, PP_Resource* addr, struct PP_CompletionCallback* callback) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + return iface->RecvFrom(udp_socket, buffer, num_bytes, addr, *callback); +} + +static int32_t Pnacl_M29_PPB_UDPSocket_Dev_SendTo(PP_Resource udp_socket, const char* buffer, int32_t num_bytes, PP_Resource addr, struct PP_CompletionCallback* callback) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + return iface->SendTo(udp_socket, buffer, num_bytes, addr, *callback); +} + +static void Pnacl_M29_PPB_UDPSocket_Dev_Close(PP_Resource udp_socket) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + iface->Close(udp_socket); +} + +static int32_t Pnacl_M29_PPB_UDPSocket_Dev_SetOption(PP_Resource udp_socket, PP_UDPSocket_Option_Dev name, struct PP_Var* value, struct PP_CompletionCallback* callback) { + const struct PPB_UDPSocket_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1.real_iface; + return iface->SetOption(udp_socket, name, *value, *callback); +} + +/* End wrapper methods for PPB_UDPSocket_Dev_0_1 */ + /* Begin wrapper methods for PPB_URLUtil_Dev_0_6 */ static void Pnacl_M17_PPB_URLUtil_Dev_Canonicalize(struct PP_Var* _struct_result, struct PP_Var* url, struct PP_URLComponents_Dev* components) { @@ -4299,6 +4345,17 @@ struct PPB_TrueTypeFont_Dev_0_1 Pnacl_Wrappers_PPB_TrueTypeFont_Dev_0_1 = { .GetTable = (int32_t (*)(PP_Resource font, uint32_t table, int32_t offset, int32_t max_data_length, struct PP_ArrayOutput output, struct PP_CompletionCallback callback))&Pnacl_M26_PPB_TrueTypeFont_Dev_GetTable }; +struct PPB_UDPSocket_Dev_0_1 Pnacl_Wrappers_PPB_UDPSocket_Dev_0_1 = { + .Create = (PP_Resource (*)(PP_Instance instance))&Pnacl_M29_PPB_UDPSocket_Dev_Create, + .IsUDPSocket = (PP_Bool (*)(PP_Resource resource))&Pnacl_M29_PPB_UDPSocket_Dev_IsUDPSocket, + .Bind = (int32_t (*)(PP_Resource udp_socket, PP_Resource addr, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_UDPSocket_Dev_Bind, + .GetBoundAddress = (PP_Resource (*)(PP_Resource udp_socket))&Pnacl_M29_PPB_UDPSocket_Dev_GetBoundAddress, + .RecvFrom = (int32_t (*)(PP_Resource udp_socket, char* buffer, int32_t num_bytes, PP_Resource* addr, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_UDPSocket_Dev_RecvFrom, + .SendTo = (int32_t (*)(PP_Resource udp_socket, const char* buffer, int32_t num_bytes, PP_Resource addr, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_UDPSocket_Dev_SendTo, + .Close = (void (*)(PP_Resource udp_socket))&Pnacl_M29_PPB_UDPSocket_Dev_Close, + .SetOption = (int32_t (*)(PP_Resource udp_socket, PP_UDPSocket_Option_Dev name, struct PP_Var value, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_UDPSocket_Dev_SetOption +}; + struct PPB_URLUtil_Dev_0_6 Pnacl_Wrappers_PPB_URLUtil_Dev_0_6 = { .Canonicalize = (struct PP_Var (*)(struct PP_Var url, struct PP_URLComponents_Dev* components))&Pnacl_M17_PPB_URLUtil_Dev_Canonicalize, .ResolveRelativeToURL = (struct PP_Var (*)(struct PP_Var base_url, struct PP_Var relative_string, struct PP_URLComponents_Dev* components))&Pnacl_M17_PPB_URLUtil_Dev_ResolveRelativeToURL, @@ -5283,6 +5340,12 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TrueTypeFont_Dev_0_1 = { .real_iface = NULL }; +static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1 = { + .iface_macro = PPB_UDPSOCKET_DEV_INTERFACE_0_1, + .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_UDPSocket_Dev_0_1, + .real_iface = NULL +}; + static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_URLUtil_Dev_0_6 = { .iface_macro = PPB_URLUTIL_DEV_INTERFACE_0_6, .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_URLUtil_Dev_0_6, @@ -5789,6 +5852,7 @@ static struct __PnaclWrapperInfo *s_ppb_wrappers[] = { &Pnacl_WrapperInfo_PPB_TextInput_Dev_0_2, &Pnacl_WrapperInfo_PPB_Trace_Event_Dev_0_1, &Pnacl_WrapperInfo_PPB_TrueTypeFont_Dev_0_1, + &Pnacl_WrapperInfo_PPB_UDPSocket_Dev_0_1, &Pnacl_WrapperInfo_PPB_URLUtil_Dev_0_6, &Pnacl_WrapperInfo_PPB_VarArray_Dev_0_1, &Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1, diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index b71178c..b82c706 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -178,6 +178,10 @@ 'proxy/truetype_font_singleton_resource.h', 'proxy/udp_socket_private_resource.cc', 'proxy/udp_socket_private_resource.h', + 'proxy/udp_socket_resource.cc', + 'proxy/udp_socket_resource.h', + 'proxy/udp_socket_resource_base.cc', + 'proxy/udp_socket_resource_base.h', 'proxy/url_loader_resource.cc', 'proxy/url_loader_resource.h', 'proxy/url_request_info_resource.cc', diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi index a834433..b5b015f 100644 --- a/ppapi/ppapi_shared.gypi +++ b/ppapi/ppapi_shared.gypi @@ -229,6 +229,8 @@ 'thunk/ppb_truetype_font_api.h', 'thunk/ppb_truetype_font_singleton_api.h', 'thunk/ppb_truetype_font_dev_thunk.cc', + 'thunk/ppb_udp_socket_api.h', + 'thunk/ppb_udp_socket_dev_thunk.cc', 'thunk/ppb_udp_socket_private_api.h', 'thunk/ppb_udp_socket_private_thunk.cc', 'thunk/ppb_url_loader_api.h', diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi index 4c6d666..6ddc4d0 100644 --- a/ppapi/ppapi_sources.gypi +++ b/ppapi/ppapi_sources.gypi @@ -77,6 +77,7 @@ 'c/dev/ppb_testing_dev.h', 'c/dev/ppb_text_input_dev.h', 'c/dev/ppb_truetype_font_dev.h', + 'c/dev/ppb_udp_socket_dev.h', 'c/dev/ppb_url_util_dev.h', 'c/dev/ppb_var_array_dev.h', 'c/dev/ppb_var_dictionary_dev.h', @@ -247,6 +248,8 @@ 'cpp/dev/text_input_dev.h', 'cpp/dev/truetype_font_dev.cc', 'cpp/dev/truetype_font_dev.h', + 'cpp/dev/udp_socket_dev.cc', + 'cpp/dev/udp_socket_dev.h', 'cpp/dev/url_util_dev.cc', 'cpp/dev/url_util_dev.h', 'cpp/dev/var_array_dev.cc', @@ -450,6 +453,8 @@ 'tests/test_tcp_socket_private.h', 'tests/test_truetype_font.cc', 'tests/test_truetype_font.h', + 'tests/test_udp_socket.cc', + 'tests/test_udp_socket.h', 'tests/test_udp_socket_private.cc', 'tests/test_udp_socket_private.h', 'tests/test_url_loader.cc', diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 0a62aa1..46346a1 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -27,6 +27,7 @@ #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/c/dev/ppb_trace_event_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" +#include "ppapi/c/dev/ppb_udp_socket_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppb_var_array_dev.h" #include "ppapi/c/dev/ppb_var_deprecated.h" diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc index a9300cce..0171dbc 100644 --- a/ppapi/proxy/resource_creation_proxy.cc +++ b/ppapi/proxy/resource_creation_proxy.cc @@ -40,6 +40,7 @@ #include "ppapi/proxy/talk_resource.h" #include "ppapi/proxy/truetype_font_resource.h" #include "ppapi/proxy/udp_socket_private_resource.h" +#include "ppapi/proxy/udp_socket_resource.h" #include "ppapi/proxy/url_loader_resource.h" #include "ppapi/proxy/url_request_info_resource.h" #include "ppapi/proxy/url_response_info_resource.h" @@ -313,6 +314,10 @@ PP_Resource ResourceCreationProxy::CreateTCPSocketPrivate( return PPB_TCPSocket_Private_Proxy::CreateProxyResource(instance); } +PP_Resource ResourceCreationProxy::CreateUDPSocket(PP_Instance instance) { + return (new UDPSocketResource(GetConnection(), instance))->GetReference(); +} + PP_Resource ResourceCreationProxy::CreateUDPSocketPrivate( PP_Instance instance) { return (new UDPSocketPrivateResource( diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h index d00a8bd..33d3b04 100644 --- a/ppapi/proxy/resource_creation_proxy.h +++ b/ppapi/proxy/resource_creation_proxy.h @@ -140,6 +140,7 @@ class ResourceCreationProxy : public InterfaceProxy, PP_Instance instance) OVERRIDE; virtual PP_Resource CreateTCPSocket(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE; + virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateWebSocket(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateX509CertificatePrivate( diff --git a/ppapi/proxy/udp_socket_private_resource.cc b/ppapi/proxy/udp_socket_private_resource.cc index 608fc00..cd2333c 100644 --- a/ppapi/proxy/udp_socket_private_resource.cc +++ b/ppapi/proxy/udp_socket_private_resource.cc @@ -4,37 +4,14 @@ #include "ppapi/proxy/udp_socket_private_resource.h" -#include <algorithm> -#include <cstring> - -#include "base/basictypes.h" -#include "base/logging.h" -#include "ppapi/c/pp_bool.h" -#include "ppapi/c/pp_completion_callback.h" -#include "ppapi/c/pp_errors.h" -#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/tracked_callback.h" namespace ppapi { namespace proxy { -const int32_t UDPSocketPrivateResource::kMaxReadSize = 1024 * 1024; -const int32_t UDPSocketPrivateResource::kMaxWriteSize = 1024 * 1024; - UDPSocketPrivateResource::UDPSocketPrivateResource(Connection connection, PP_Instance instance) - : PluginResource(connection, instance), - bound_(false), - closed_(false), - read_buffer_(NULL), - bytes_to_read_(-1) { - recvfrom_addr_.size = 0; - memset(recvfrom_addr_.data, 0, - arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data)); - bound_addr_.size = 0; - memset(bound_addr_.data, 0, - arraysize(bound_addr_.data) * sizeof(*bound_addr_.data)); - - SendCreate(BROWSER, PpapiHostMsg_UDPSocketPrivate_Create()); + : UDPSocketResourceBase(connection, instance) { } UDPSocketPrivateResource::~UDPSocketPrivateResource() { @@ -48,80 +25,29 @@ UDPSocketPrivateResource::AsPPB_UDPSocket_Private_API() { int32_t UDPSocketPrivateResource::SetSocketFeature( PP_UDPSocketFeature_Private name, PP_Var value) { - if (bound_ || closed_) - return PP_ERROR_FAILED; - - switch (name) { - case PP_UDPSOCKETFEATURE_ADDRESS_REUSE: - case PP_UDPSOCKETFEATURE_BROADCAST: - if (value.type != PP_VARTYPE_BOOL) - return PP_ERROR_BADARGUMENT; - SendBoolSocketFeature(static_cast<int32_t>(name), - PP_ToBool(value.value.as_bool)); - break; - default: - return PP_ERROR_BADARGUMENT; - } - return PP_OK; + return SetSocketFeatureImpl(name, value); } int32_t UDPSocketPrivateResource::Bind( const PP_NetAddress_Private* addr, scoped_refptr<TrackedCallback> callback) { - if (!addr) - return PP_ERROR_BADARGUMENT; - if (bound_ || closed_) - return PP_ERROR_FAILED; - if (TrackedCallback::IsPending(bind_callback_)) - return PP_ERROR_INPROGRESS; - - bind_callback_ = callback; - - // Send the request, the browser will call us back via BindReply. - SendBind(*addr); - return PP_OK_COMPLETIONPENDING; + return BindImpl(addr, callback); } PP_Bool UDPSocketPrivateResource::GetBoundAddress(PP_NetAddress_Private* addr) { - if (!addr || !bound_ || closed_) - return PP_FALSE; - - *addr = bound_addr_; - return PP_TRUE; + return GetBoundAddressImpl(addr); } int32_t UDPSocketPrivateResource::RecvFrom( char* buffer, int32_t num_bytes, scoped_refptr<TrackedCallback> callback) { - if (!buffer || num_bytes <= 0) - return PP_ERROR_BADARGUMENT; - if (!bound_) - return PP_ERROR_FAILED; - if (TrackedCallback::IsPending(recvfrom_callback_)) - return PP_ERROR_INPROGRESS; - - read_buffer_ = buffer; - bytes_to_read_ = std::min(num_bytes, kMaxReadSize); - recvfrom_callback_ = callback; - - // Send the request, the browser will call us back via RecvFromReply. - SendRecvFrom(bytes_to_read_); - return PP_OK_COMPLETIONPENDING; + return RecvFromImpl(buffer, num_bytes, NULL, callback); } PP_Bool UDPSocketPrivateResource::GetRecvFromAddress( PP_NetAddress_Private* addr) { - if (!addr) - return PP_FALSE; - *addr = recvfrom_addr_; - return PP_TRUE; -} - -void UDPSocketPrivateResource::PostAbortIfNecessary( - scoped_refptr<TrackedCallback>* callback) { - if (TrackedCallback::IsPending(*callback)) - (*callback)->PostAbort(); + return GetRecvFromAddressImpl(addr); } int32_t UDPSocketPrivateResource::SendTo( @@ -129,123 +55,11 @@ int32_t UDPSocketPrivateResource::SendTo( int32_t num_bytes, const PP_NetAddress_Private* addr, scoped_refptr<TrackedCallback> callback) { - if (!buffer || num_bytes <= 0 || !addr) - return PP_ERROR_BADARGUMENT; - if (!bound_) - return PP_ERROR_FAILED; - if (TrackedCallback::IsPending(sendto_callback_)) - return PP_ERROR_INPROGRESS; - - if (num_bytes > kMaxWriteSize) - num_bytes = kMaxWriteSize; - - sendto_callback_ = callback; - - // Send the request, the browser will call us back via SendToReply. - SendSendTo(std::string(buffer, num_bytes), *addr); - return PP_OK_COMPLETIONPENDING; + return SendToImpl(buffer, num_bytes, addr, callback); } void UDPSocketPrivateResource::Close() { - if(closed_) - return; - - bound_ = false; - closed_ = true; - - SendClose(); - - PostAbortIfNecessary(&bind_callback_); - PostAbortIfNecessary(&recvfrom_callback_); - PostAbortIfNecessary(&sendto_callback_); -} - -void UDPSocketPrivateResource::SendBoolSocketFeature(int32_t name, bool value) { - PpapiHostMsg_UDPSocketPrivate_SetBoolSocketFeature msg(name, value); - Post(BROWSER, msg); -} - -void UDPSocketPrivateResource::SendBind(const PP_NetAddress_Private& addr) { - PpapiHostMsg_UDPSocketPrivate_Bind msg(addr); - Call<PpapiPluginMsg_UDPSocketPrivate_BindReply>( - BROWSER, - msg, - base::Bind(&UDPSocketPrivateResource::OnPluginMsgBindReply, - base::Unretained(this))); -} - -void UDPSocketPrivateResource::SendRecvFrom(int32_t num_bytes) { - PpapiHostMsg_UDPSocketPrivate_RecvFrom msg(num_bytes); - Call<PpapiPluginMsg_UDPSocketPrivate_RecvFromReply>( - BROWSER, - msg, - base::Bind(&UDPSocketPrivateResource::OnPluginMsgRecvFromReply, - base::Unretained(this))); -} - -void UDPSocketPrivateResource::SendSendTo(const std::string& buffer, - const PP_NetAddress_Private& addr) { - PpapiHostMsg_UDPSocketPrivate_SendTo msg(buffer, addr); - Call<PpapiPluginMsg_UDPSocketPrivate_SendToReply>( - BROWSER, - msg, - base::Bind(&UDPSocketPrivateResource::OnPluginMsgSendToReply, - base::Unretained(this))); -} - -void UDPSocketPrivateResource::SendClose() { - PpapiHostMsg_UDPSocketPrivate_Close msg; - Post(BROWSER, msg); -} - -void UDPSocketPrivateResource::OnPluginMsgBindReply( - const ResourceMessageReplyParams& params, - const PP_NetAddress_Private& bound_addr) { - if (!TrackedCallback::IsPending(bind_callback_)) { - NOTREACHED(); - return; - } - if (params.result() == PP_OK) - bound_ = true; - bound_addr_ = bound_addr; - bind_callback_->Run(params.result()); -} - -void UDPSocketPrivateResource::OnPluginMsgRecvFromReply( - const ResourceMessageReplyParams& params, - const std::string& data, - const PP_NetAddress_Private& addr) { - if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) { - NOTREACHED(); - return; - } - bool succeeded = (params.result() == PP_OK); - 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; - recvfrom_addr_ = addr; - - if (succeeded) - recvfrom_callback_->Run(static_cast<int32_t>(data.size())); - else - recvfrom_callback_->Run(params.result()); -} - -void UDPSocketPrivateResource::OnPluginMsgSendToReply( - const ResourceMessageReplyParams& params, - int32_t bytes_written) { - if (!TrackedCallback::IsPending(sendto_callback_)) { - NOTREACHED(); - return; - } - if (params.result() == PP_OK) - sendto_callback_->Run(bytes_written); - else - sendto_callback_->Run(params.result()); + CloseImpl(); } } // namespace proxy diff --git a/ppapi/proxy/udp_socket_private_resource.h b/ppapi/proxy/udp_socket_private_resource.h index 6403f6b..48f5d71 100644 --- a/ppapi/proxy/udp_socket_private_resource.h +++ b/ppapi/proxy/udp_socket_private_resource.h @@ -7,29 +7,20 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "ppapi/proxy/plugin_resource.h" #include "ppapi/proxy/ppapi_proxy_export.h" -#include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/proxy/udp_socket_resource_base.h" #include "ppapi/thunk/ppb_udp_socket_private_api.h" namespace ppapi { namespace proxy { class PPAPI_PROXY_EXPORT UDPSocketPrivateResource - : public PluginResource, + : public UDPSocketResourceBase, public thunk::PPB_UDPSocket_Private_API { public: - UDPSocketPrivateResource(Connection connection, - PP_Instance instance); + UDPSocketPrivateResource(Connection connection, PP_Instance instance); virtual ~UDPSocketPrivateResource(); - // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_RecvFrom - // message is allowed to request. - static const int32_t kMaxReadSize; - // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_SendTo - // message is allowed to carry. - static const int32_t kMaxWriteSize; - // PluginResource implementation. virtual thunk::PPB_UDPSocket_Private_API* AsPPB_UDPSocket_Private_API() OVERRIDE; @@ -51,37 +42,6 @@ class PPAPI_PROXY_EXPORT UDPSocketPrivateResource virtual void Close() OVERRIDE; private: - void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback); - - void SendBoolSocketFeature(int32_t name, bool value); - void SendBind(const PP_NetAddress_Private& addr); - void SendRecvFrom(int32_t num_bytes); - void SendSendTo(const std::string& buffer, - const PP_NetAddress_Private& addr); - void SendClose(); - - // IPC message handlers. - void OnPluginMsgBindReply(const ResourceMessageReplyParams& params, - const PP_NetAddress_Private& bound_addr); - void OnPluginMsgRecvFromReply(const ResourceMessageReplyParams& params, - const std::string& data, - const PP_NetAddress_Private& addr); - void OnPluginMsgSendToReply(const ResourceMessageReplyParams& params, - int32_t bytes_written); - - bool bound_; - bool closed_; - - scoped_refptr<TrackedCallback> bind_callback_; - scoped_refptr<TrackedCallback> recvfrom_callback_; - scoped_refptr<TrackedCallback> sendto_callback_; - - char* read_buffer_; - int32_t bytes_to_read_; - - PP_NetAddress_Private recvfrom_addr_; - PP_NetAddress_Private bound_addr_; - DISALLOW_COPY_AND_ASSIGN(UDPSocketPrivateResource); }; diff --git a/ppapi/proxy/udp_socket_resource.cc b/ppapi/proxy/udp_socket_resource.cc new file mode 100644 index 0000000..9a1dbd6 --- /dev/null +++ b/ppapi/proxy/udp_socket_resource.cc @@ -0,0 +1,99 @@ +// 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/udp_socket_resource.h" + +#include "ppapi/shared_impl/tracked_callback.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/ppb_net_address_api.h" +#include "ppapi/thunk/resource_creation_api.h" + +namespace ppapi { +namespace proxy { + +namespace { + +typedef thunk::EnterResourceNoLock<thunk::PPB_NetAddress_API> + EnterNetAddressNoLock; + +} // namespace + +UDPSocketResource::UDPSocketResource(Connection connection, + PP_Instance instance) + : UDPSocketResourceBase(connection, instance) { +} + +UDPSocketResource::~UDPSocketResource() { +} + +thunk::PPB_UDPSocket_API* UDPSocketResource::AsPPB_UDPSocket_API() { + return this; +} + +int32_t UDPSocketResource::Bind(PP_Resource addr, + scoped_refptr<TrackedCallback> callback) { + EnterNetAddressNoLock enter(addr, true); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + + return BindImpl(&enter.object()->GetNetAddressPrivate(), callback); +} + +PP_Resource UDPSocketResource::GetBoundAddress() { + PP_NetAddress_Private addr_private; + if (!GetBoundAddressImpl(&addr_private)) + return 0; + + thunk::EnterResourceCreationNoLock enter(pp_instance()); + if (enter.failed()) + return 0; + return enter.functions()->CreateNetAddressFromNetAddressPrivate( + pp_instance(), addr_private); +} + +int32_t UDPSocketResource::RecvFrom(char* buffer, + int32_t num_bytes, + PP_Resource* addr, + scoped_refptr<TrackedCallback> callback) { + return RecvFromImpl(buffer, num_bytes, addr, callback); +} + +int32_t UDPSocketResource::SendTo(const char* buffer, + int32_t num_bytes, + PP_Resource addr, + scoped_refptr<TrackedCallback> callback) { + EnterNetAddressNoLock enter(addr, true); + if (enter.failed()) + return PP_ERROR_BADARGUMENT; + + return SendToImpl(buffer, num_bytes, &enter.object()->GetNetAddressPrivate(), + callback); +} + +void UDPSocketResource::Close() { + CloseImpl(); +} + +int32_t UDPSocketResource::SetOption( + PP_UDPSocket_Option_Dev name, + const PP_Var& value, + scoped_refptr<TrackedCallback> /* callback */) { + // TODO(yzshen): Add support for other options. + PP_UDPSocketFeature_Private feature; + switch (name) { + case PP_UDPSOCKET_OPTION_ADDRESS_REUSE: + feature = PP_UDPSOCKETFEATURE_ADDRESS_REUSE; + break; + case PP_UDPSOCKET_OPTION_BROADCAST: + feature = PP_UDPSOCKETFEATURE_BROADCAST; + break; + default: + return PP_ERROR_NOTSUPPORTED; + } + + return SetSocketFeatureImpl(feature, value); +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/udp_socket_resource.h b/ppapi/proxy/udp_socket_resource.h new file mode 100644 index 0000000..ac24187 --- /dev/null +++ b/ppapi/proxy/udp_socket_resource.h @@ -0,0 +1,50 @@ +// 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_UDP_SOCKET_RESOURCE_H_ +#define PPAPI_PROXY_UDP_SOCKET_RESOURCE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/proxy/udp_socket_resource_base.h" +#include "ppapi/thunk/ppb_udp_socket_api.h" + +namespace ppapi { +namespace proxy { + +class PPAPI_PROXY_EXPORT UDPSocketResource : public UDPSocketResourceBase, + public thunk::PPB_UDPSocket_API { + public: + UDPSocketResource(Connection connection, PP_Instance instance); + virtual ~UDPSocketResource(); + + // PluginResource implementation. + virtual thunk::PPB_UDPSocket_API* AsPPB_UDPSocket_API() OVERRIDE; + + // thunk::PPB_UDPSocket_API implementation. + virtual int32_t Bind(PP_Resource addr, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual PP_Resource GetBoundAddress() OVERRIDE; + virtual int32_t RecvFrom(char* buffer, + int32_t num_bytes, + PP_Resource* addr, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual int32_t SendTo(const char* buffer, + int32_t num_bytes, + PP_Resource addr, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + virtual void Close() OVERRIDE; + virtual int32_t SetOption(PP_UDPSocket_Option_Dev name, + const PP_Var& value, + scoped_refptr<TrackedCallback> callback) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(UDPSocketResource); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_UDP_SOCKET_RESOURCE_H_ diff --git a/ppapi/proxy/udp_socket_resource_base.cc b/ppapi/proxy/udp_socket_resource_base.cc new file mode 100644 index 0000000..5d31890 --- /dev/null +++ b/ppapi/proxy/udp_socket_resource_base.cc @@ -0,0 +1,240 @@ +// 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/udp_socket_resource_base.h" + +#include <algorithm> +#include <cstring> + +#include "base/logging.h" +#include "ppapi/c/pp_bool.h" +#include "ppapi/c/pp_completion_callback.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/resource_creation_api.h" + +namespace ppapi { +namespace proxy { + +const int32_t UDPSocketResourceBase::kMaxReadSize = 1024 * 1024; +const int32_t UDPSocketResourceBase::kMaxWriteSize = 1024 * 1024; + +UDPSocketResourceBase::UDPSocketResourceBase(Connection connection, + PP_Instance instance) + : PluginResource(connection, instance), + bound_(false), + closed_(false), + read_buffer_(NULL), + bytes_to_read_(-1) { + recvfrom_addr_.size = 0; + memset(recvfrom_addr_.data, 0, + arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data)); + bound_addr_.size = 0; + memset(bound_addr_.data, 0, + arraysize(bound_addr_.data) * sizeof(*bound_addr_.data)); + + SendCreate(BROWSER, PpapiHostMsg_UDPSocketPrivate_Create()); +} + +UDPSocketResourceBase::~UDPSocketResourceBase() { +} + +int32_t UDPSocketResourceBase::SetSocketFeatureImpl( + PP_UDPSocketFeature_Private name, + const PP_Var& value) { + if (bound_ || closed_) + return PP_ERROR_FAILED; + + switch (name) { + case PP_UDPSOCKETFEATURE_ADDRESS_REUSE: + case PP_UDPSOCKETFEATURE_BROADCAST: { + if (value.type != PP_VARTYPE_BOOL) + return PP_ERROR_BADARGUMENT; + Post(BROWSER, + PpapiHostMsg_UDPSocketPrivate_SetBoolSocketFeature( + static_cast<int32_t>(name), PP_ToBool(value.value.as_bool))); + break; + } + default: { + return PP_ERROR_BADARGUMENT; + } + } + return PP_OK; +} + +int32_t UDPSocketResourceBase::BindImpl( + const PP_NetAddress_Private* addr, + scoped_refptr<TrackedCallback> callback) { + if (!addr) + return PP_ERROR_BADARGUMENT; + if (bound_ || closed_) + return PP_ERROR_FAILED; + if (TrackedCallback::IsPending(bind_callback_)) + return PP_ERROR_INPROGRESS; + + bind_callback_ = callback; + + // Send the request, the browser will call us back via BindReply. + Call<PpapiPluginMsg_UDPSocketPrivate_BindReply>( + BROWSER, + PpapiHostMsg_UDPSocketPrivate_Bind(*addr), + base::Bind(&UDPSocketResourceBase::OnPluginMsgBindReply, + base::Unretained(this))); + return PP_OK_COMPLETIONPENDING; +} + +PP_Bool UDPSocketResourceBase::GetBoundAddressImpl( + PP_NetAddress_Private* addr) { + if (!addr || !bound_ || closed_) + return PP_FALSE; + + *addr = bound_addr_; + return PP_TRUE; +} + +int32_t UDPSocketResourceBase::RecvFromImpl( + char* buffer, + int32_t num_bytes, + PP_Resource* addr, + scoped_refptr<TrackedCallback> callback) { + if (!buffer || num_bytes <= 0) + return PP_ERROR_BADARGUMENT; + if (!bound_) + return PP_ERROR_FAILED; + if (TrackedCallback::IsPending(recvfrom_callback_)) + return PP_ERROR_INPROGRESS; + + read_buffer_ = buffer; + bytes_to_read_ = std::min(num_bytes, kMaxReadSize); + recvfrom_callback_ = callback; + + // Send the request, the browser will call us back via RecvFromReply. + Call<PpapiPluginMsg_UDPSocketPrivate_RecvFromReply>( + BROWSER, + PpapiHostMsg_UDPSocketPrivate_RecvFrom(bytes_to_read_), + base::Bind(&UDPSocketResourceBase::OnPluginMsgRecvFromReply, + base::Unretained(this), addr)); + return PP_OK_COMPLETIONPENDING; +} + +PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl( + PP_NetAddress_Private* addr) { + if (!addr) + return PP_FALSE; + *addr = recvfrom_addr_; + return PP_TRUE; +} + +int32_t UDPSocketResourceBase::SendToImpl( + const char* buffer, + int32_t num_bytes, + const PP_NetAddress_Private* addr, + scoped_refptr<TrackedCallback> callback) { + if (!buffer || num_bytes <= 0 || !addr) + return PP_ERROR_BADARGUMENT; + if (!bound_) + return PP_ERROR_FAILED; + if (TrackedCallback::IsPending(sendto_callback_)) + return PP_ERROR_INPROGRESS; + + if (num_bytes > kMaxWriteSize) + num_bytes = kMaxWriteSize; + + sendto_callback_ = callback; + + // Send the request, the browser will call us back via SendToReply. + Call<PpapiPluginMsg_UDPSocketPrivate_SendToReply>( + BROWSER, + PpapiHostMsg_UDPSocketPrivate_SendTo( + std::string(buffer, num_bytes), *addr), + base::Bind(&UDPSocketResourceBase::OnPluginMsgSendToReply, + base::Unretained(this))); + return PP_OK_COMPLETIONPENDING; +} + +void UDPSocketResourceBase::CloseImpl() { + if(closed_) + return; + + bound_ = false; + closed_ = true; + + Post(BROWSER, PpapiHostMsg_UDPSocketPrivate_Close()); + + PostAbortIfNecessary(&bind_callback_); + PostAbortIfNecessary(&recvfrom_callback_); + PostAbortIfNecessary(&sendto_callback_); +} + +void UDPSocketResourceBase::PostAbortIfNecessary( + scoped_refptr<TrackedCallback>* callback) { + if (TrackedCallback::IsPending(*callback)) + (*callback)->PostAbort(); +} + +void UDPSocketResourceBase::OnPluginMsgBindReply( + const ResourceMessageReplyParams& params, + const PP_NetAddress_Private& bound_addr) { + if (!TrackedCallback::IsPending(bind_callback_)) { + NOTREACHED(); + return; + } + if (params.result() == PP_OK) + bound_ = true; + bound_addr_ = bound_addr; + bind_callback_->Run(params.result()); +} + +void UDPSocketResourceBase::OnPluginMsgRecvFromReply( + PP_Resource* output_addr, + const ResourceMessageReplyParams& params, + const std::string& data, + const PP_NetAddress_Private& addr) { + if (!TrackedCallback::IsPending(recvfrom_callback_)) { + NOTREACHED(); + return; + } + bool succeeded = (params.result() == PP_OK); + if (succeeded && output_addr) { + thunk::EnterResourceCreationNoLock enter(pp_instance()); + if (enter.succeeded()) { + *output_addr = enter.functions()->CreateNetAddressFromNetAddressPrivate( + pp_instance(), addr); + } else { + succeeded = false; + } + } + + 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; + recvfrom_addr_ = addr; + + if (succeeded) + recvfrom_callback_->Run(static_cast<int32_t>(data.size())); + else + recvfrom_callback_->Run(params.result()); +} + +void UDPSocketResourceBase::OnPluginMsgSendToReply( + const ResourceMessageReplyParams& params, + int32_t bytes_written) { + if (!TrackedCallback::IsPending(sendto_callback_)) { + NOTREACHED(); + return; + } + if (params.result() == PP_OK) + sendto_callback_->Run(bytes_written); + else + sendto_callback_->Run(params.result()); +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/udp_socket_resource_base.h b/ppapi/proxy/udp_socket_resource_base.h new file mode 100644 index 0000000..b3a6669 --- /dev/null +++ b/ppapi/proxy/udp_socket_resource_base.h @@ -0,0 +1,86 @@ +// 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_UDP_SOCKET_SHARED_H_ +#define PPAPI_PROXY_UDP_SOCKET_SHARED_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "ppapi/c/private/ppb_net_address_private.h" +#include "ppapi/c/private/ppb_udp_socket_private.h" +#include "ppapi/proxy/plugin_resource.h" +#include "ppapi/proxy/ppapi_proxy_export.h" +#include "ppapi/shared_impl/tracked_callback.h" + +namespace ppapi { +namespace proxy { + +class ResourceMessageReplyParams; + +class PPAPI_PROXY_EXPORT UDPSocketResourceBase: public PluginResource { + public: + // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_RecvFrom + // message is allowed to request. + static const int32_t kMaxReadSize; + // The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_SendTo + // message is allowed to carry. + static const int32_t kMaxWriteSize; + + protected: + UDPSocketResourceBase(Connection connection, PP_Instance instance); + virtual ~UDPSocketResourceBase(); + + int32_t SetSocketFeatureImpl(PP_UDPSocketFeature_Private name, + const PP_Var& value); + int32_t BindImpl(const PP_NetAddress_Private* addr, + scoped_refptr<TrackedCallback> callback); + PP_Bool GetBoundAddressImpl(PP_NetAddress_Private* addr); + // |addr| could be NULL to indicate that an output value is not needed. + int32_t RecvFromImpl(char* buffer, + int32_t num_bytes, + PP_Resource* addr, + scoped_refptr<TrackedCallback> callback); + PP_Bool GetRecvFromAddressImpl(PP_NetAddress_Private* addr); + int32_t SendToImpl(const char* buffer, + int32_t num_bytes, + const PP_NetAddress_Private* addr, + scoped_refptr<TrackedCallback> callback); + void CloseImpl(); + + private: + void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback); + + // IPC message handlers. + void OnPluginMsgBindReply(const ResourceMessageReplyParams& params, + const PP_NetAddress_Private& bound_addr); + void OnPluginMsgRecvFromReply(PP_Resource* output_addr, + const ResourceMessageReplyParams& params, + const std::string& data, + const PP_NetAddress_Private& addr); + void OnPluginMsgSendToReply(const ResourceMessageReplyParams& params, + int32_t bytes_written); + + bool bound_; + bool closed_; + + scoped_refptr<TrackedCallback> bind_callback_; + scoped_refptr<TrackedCallback> recvfrom_callback_; + scoped_refptr<TrackedCallback> sendto_callback_; + + char* read_buffer_; + int32_t bytes_to_read_; + + PP_NetAddress_Private recvfrom_addr_; + PP_NetAddress_Private bound_addr_; + + DISALLOW_COPY_AND_ASSIGN(UDPSocketResourceBase); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_UDP_SOCKET_SHARED_H_ diff --git a/ppapi/shared_impl/resource.h b/ppapi/shared_impl/resource.h index 05b3d51..72a060c 100644 --- a/ppapi/shared_impl/resource.h +++ b/ppapi/shared_impl/resource.h @@ -65,6 +65,7 @@ F(PPB_TCPServerSocket_Private_API) \ F(PPB_TCPSocket_API) \ F(PPB_TCPSocket_Private_API) \ + F(PPB_UDPSocket_API) \ F(PPB_UDPSocket_Private_API) \ F(PPB_URLLoader_API) \ F(PPB_URLRequestInfo_API) \ diff --git a/ppapi/tests/all_c_includes.h b/ppapi/tests/all_c_includes.h index 4a8ae13..1a18294 100644 --- a/ppapi/tests/all_c_includes.h +++ b/ppapi/tests/all_c_includes.h @@ -31,6 +31,7 @@ #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/c/dev/ppb_trace_event_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" +#include "ppapi/c/dev/ppb_udp_socket_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppb_var_array_dev.h" #include "ppapi/c/dev/ppb_var_deprecated.h" diff --git a/ppapi/tests/all_cpp_includes.h b/ppapi/tests/all_cpp_includes.h index 37a4100..717d743 100644 --- a/ppapi/tests/all_cpp_includes.h +++ b/ppapi/tests/all_cpp_includes.h @@ -28,6 +28,7 @@ #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/udp_socket_dev.h" #include "ppapi/cpp/dev/url_util_dev.h" #include "ppapi/cpp/dev/var_array_dev.h" #include "ppapi/cpp/dev/var_dictionary_dev.h" diff --git a/ppapi/tests/test_udp_socket.cc b/ppapi/tests/test_udp_socket.cc new file mode 100644 index 0000000..d3bb27c --- /dev/null +++ b/ppapi/tests/test_udp_socket.cc @@ -0,0 +1,271 @@ +// 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_udp_socket.h" + +#include <vector> + +#include "ppapi/cpp/dev/tcp_socket_dev.h" +#include "ppapi/cpp/dev/udp_socket_dev.h" +#include "ppapi/cpp/pass_ref.h" +#include "ppapi/cpp/var.h" +#include "ppapi/tests/test_utils.h" +#include "ppapi/tests/testing_instance.h" + +REGISTER_TEST_CASE(UDPSocket); + +namespace { + +const uint16_t kPortScanFrom = 1024; +const uint16_t kPortScanTo = 4096; + +pp::NetAddress_Dev ReplacePort(const pp::InstanceHandle& instance, + const pp::NetAddress_Dev& addr, + uint16_t port) { + switch (addr.GetFamily()) { + case PP_NETADDRESS_FAMILY_IPV4: { + PP_NetAddress_IPv4_Dev ipv4_addr; + if (!addr.DescribeAsIPv4Address(&ipv4_addr)) + break; + ipv4_addr.port = ConvertToNetEndian16(port); + return pp::NetAddress_Dev(instance, ipv4_addr); + } + case PP_NETADDRESS_FAMILY_IPV6: { + PP_NetAddress_IPv6_Dev ipv6_addr; + if (!addr.DescribeAsIPv6Address(&ipv6_addr)) + break; + ipv6_addr.port = ConvertToNetEndian16(port); + return pp::NetAddress_Dev(instance, ipv6_addr); + } + default: { + PP_NOTREACHED(); + } + } + return pp::NetAddress_Dev(); +} + +} // namespace + +TestUDPSocket::TestUDPSocket(TestingInstance* instance) : TestCase(instance) { +} + +bool TestUDPSocket::Init() { + bool tcp_socket_is_available = pp::TCPSocket_Dev::IsAvailable(); + if (!tcp_socket_is_available) + instance_->AppendError("PPB_TCPSocket interface not available"); + + bool udp_socket_is_available = pp::UDPSocket_Dev::IsAvailable(); + if (!udp_socket_is_available) + instance_->AppendError("PPB_UDPSocket interface not available"); + + bool net_address_is_available = pp::NetAddress_Dev::IsAvailable(); + if (!net_address_is_available) + instance_->AppendError("PPB_NetAddress interface not available"); + + std::string host; + uint16_t port = 0; + bool init_address = + GetLocalHostPort(instance_->pp_instance(), &host, &port) && + ResolveHost(instance_->pp_instance(), host, port, &address_); + if (!init_address) + instance_->AppendError("Can't init address"); + + return tcp_socket_is_available && + udp_socket_is_available && + net_address_is_available && + init_address && + CheckTestingInterface() && + EnsureRunningOverHTTP(); +} + +void TestUDPSocket::RunTests(const std::string& filter) { + RUN_CALLBACK_TEST(TestUDPSocket, ReadWrite, filter); + RUN_CALLBACK_TEST(TestUDPSocket, Broadcast, filter); + RUN_CALLBACK_TEST(TestUDPSocket, SetOption, filter); +} + +std::string TestUDPSocket::GetLocalAddress(pp::NetAddress_Dev* address) { + pp::TCPSocket_Dev socket(instance_); + TestCompletionCallback callback(instance_->pp_instance(), callback_type()); + callback.WaitForResult(socket.Connect(address_, callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_EQ(PP_OK, callback.result()); + *address = socket.GetLocalAddress(); + ASSERT_NE(0, address->pp_resource()); + socket.Close(); + PASS(); +} + +std::string TestUDPSocket::SetBroadcastOptions(pp::UDPSocket_Dev* socket) { + TestCompletionCallback callback_1(instance_->pp_instance(), callback_type()); + callback_1.WaitForResult(socket->SetOption( + PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(true), + callback_1.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback_1); + ASSERT_EQ(PP_OK, callback_1.result()); + + TestCompletionCallback callback_2(instance_->pp_instance(), callback_type()); + callback_2.WaitForResult(socket->SetOption( + PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback_2.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback_2); + ASSERT_EQ(PP_OK, callback_2.result()); + + PASS(); +} + +std::string TestUDPSocket::BindUDPSocket(pp::UDPSocket_Dev* socket, + const pp::NetAddress_Dev& address) { + TestCompletionCallback callback(instance_->pp_instance(), callback_type()); + callback.WaitForResult(socket->Bind(address, callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_EQ(PP_OK, callback.result()); + PASS(); +} + +std::string TestUDPSocket::LookupPortAndBindUDPSocket( + pp::UDPSocket_Dev* socket, + pp::NetAddress_Dev* address) { + pp::NetAddress_Dev base_address; + ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address)); + + bool is_free_port_found = false; + for (uint16_t port = kPortScanFrom; port < kPortScanTo; ++port) { + pp::NetAddress_Dev new_address = ReplacePort(instance_, base_address, port); + ASSERT_NE(0, new_address.pp_resource()); + if (BindUDPSocket(socket, new_address).empty()) { + is_free_port_found = true; + break; + } + } + if (!is_free_port_found) + return "Can't find available port"; + + *address = socket->GetBoundAddress(); + ASSERT_NE(0, address->pp_resource()); + + PASS(); +} + +std::string TestUDPSocket::ReadSocket(pp::UDPSocket_Dev* socket, + pp::NetAddress_Dev* address, + size_t size, + std::string* message) { + std::vector<char> buffer(size); + TestCompletionCallbackWithOutput<pp::NetAddress_Dev> callback( + instance_->pp_instance(), callback_type()); + callback.WaitForResult( + socket->RecvFrom(&buffer[0], size, callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_FALSE(callback.result() < 0); + ASSERT_EQ(size, static_cast<size_t>(callback.result())); + *address = callback.output(); + message->assign(buffer.begin(), buffer.end()); + PASS(); +} + +std::string TestUDPSocket::PassMessage(pp::UDPSocket_Dev* target, + pp::UDPSocket_Dev* source, + const pp::NetAddress_Dev& target_address, + const std::string& message, + pp::NetAddress_Dev* recvfrom_address) { + TestCompletionCallback callback(instance_->pp_instance(), callback_type()); + int32_t rv = source->SendTo(message.c_str(), message.size(), + target_address, + callback.GetCallback()); + std::string str; + ASSERT_SUBTEST_SUCCESS(ReadSocket(target, recvfrom_address, message.size(), + &str)); + + callback.WaitForResult(rv); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_FALSE(callback.result() < 0); + ASSERT_EQ(message.size(), static_cast<size_t>(callback.result())); + ASSERT_EQ(message, str); + PASS(); +} + +std::string TestUDPSocket::TestReadWrite() { + pp::UDPSocket_Dev server_socket(instance_), client_socket(instance_); + pp::NetAddress_Dev server_address, client_address; + + ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket, + &server_address)); + ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket, + &client_address)); + const std::string message = "Simple message that will be sent via UDP"; + pp::NetAddress_Dev recvfrom_address; + ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket, &client_socket, + server_address, message, + &recvfrom_address)); + ASSERT_TRUE(EqualNetAddress(recvfrom_address, client_address)); + + server_socket.Close(); + client_socket.Close(); + + if (server_socket.GetBoundAddress().pp_resource() != 0) + return "PPB_UDPSocket::GetBoundAddress: expected failure"; + + PASS(); +} + +std::string TestUDPSocket::TestBroadcast() { + pp::UDPSocket_Dev server1(instance_), server2(instance_); + + ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server1)); + ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server2)); + + PP_NetAddress_IPv4_Dev any_ipv4_address = { 0, { 0, 0, 0, 0 } }; + pp::NetAddress_Dev any_address(instance_, any_ipv4_address); + ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server1, any_address)); + // Fill port field of |server_address|. + pp::NetAddress_Dev server_address = server1.GetBoundAddress(); + ASSERT_NE(0, server_address.pp_resource()); + ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server2, server_address)); + + PP_NetAddress_IPv4_Dev server_ipv4_address; + ASSERT_TRUE(server_address.DescribeAsIPv4Address(&server_ipv4_address)); + + PP_NetAddress_IPv4_Dev broadcast_ipv4_address = { + server_ipv4_address.port, { 0xff, 0xff, 0xff, 0xff } + }; + pp::NetAddress_Dev broadcast_address(instance_, broadcast_ipv4_address); + + std::string message; + const std::string first_message = "first message"; + const std::string second_message = "second_message"; + + pp::NetAddress_Dev recvfrom_address; + ASSERT_SUBTEST_SUCCESS(PassMessage(&server1, &server2, broadcast_address, + first_message, &recvfrom_address)); + // |first_message| was also received by |server2|. + ASSERT_SUBTEST_SUCCESS(ReadSocket(&server2, &recvfrom_address, + first_message.size(), &message)); + ASSERT_EQ(first_message, message); + + ASSERT_SUBTEST_SUCCESS(PassMessage(&server2, &server1, broadcast_address, + second_message, &recvfrom_address)); + // |second_message| was also received by |server1|. + ASSERT_SUBTEST_SUCCESS(ReadSocket(&server1, &recvfrom_address, + second_message.size(), &message)); + ASSERT_EQ(second_message, message); + + server1.Close(); + server2.Close(); + PASS(); +} + +std::string TestUDPSocket::TestSetOption() { + pp::UDPSocket_Dev socket(instance_); + + ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&socket)); + + // Try to pass incorrect option value's type. + TestCompletionCallback callback(instance_->pp_instance(), callback_type()); + callback.WaitForResult(socket.SetOption( + PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(1), callback.GetCallback())); + CHECK_CALLBACK_BEHAVIOR(callback); + ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result()); + + PASS(); +} diff --git a/ppapi/tests/test_udp_socket.h b/ppapi/tests/test_udp_socket.h new file mode 100644 index 0000000..986806c --- /dev/null +++ b/ppapi/tests/test_udp_socket.h @@ -0,0 +1,50 @@ +// 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_TESTS_TEST_UDP_SOCKET_H_ +#define PPAPI_TESTS_TEST_UDP_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 UDPSocket_Dev; +} + +class TestUDPSocket: public TestCase { + public: + explicit TestUDPSocket(TestingInstance* instance); + + // TestCase implementation. + virtual bool Init(); + virtual void RunTests(const std::string& filter); + + private: + std::string GetLocalAddress(pp::NetAddress_Dev* address); + std::string SetBroadcastOptions(pp::UDPSocket_Dev* socket); + std::string BindUDPSocket(pp::UDPSocket_Dev* socket, + const pp::NetAddress_Dev& address); + std::string LookupPortAndBindUDPSocket(pp::UDPSocket_Dev* socket, + pp::NetAddress_Dev* address); + std::string ReadSocket(pp::UDPSocket_Dev* socket, + pp::NetAddress_Dev* address, + size_t size, + std::string* message); + std::string PassMessage(pp::UDPSocket_Dev* target, + pp::UDPSocket_Dev* source, + const pp::NetAddress_Dev& target_address, + const std::string& message, + pp::NetAddress_Dev* recvfrom_address); + + std::string TestReadWrite(); + std::string TestBroadcast(); + std::string TestSetOption(); + + pp::NetAddress_Dev address_; +}; + +#endif // PPAPI_TESTS_TEST_UDP_SOCKET_H_ diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h index e953811..db1ab46 100644 --- a/ppapi/thunk/interfaces_ppb_public_dev.h +++ b/ppapi/thunk/interfaces_ppb_public_dev.h @@ -42,6 +42,8 @@ PROXIED_IFACE(PPB_Instance, PPB_TEXTINPUT_DEV_INTERFACE_0_2, PPB_TextInput_Dev_0_2) PROXIED_IFACE(NoAPIName, PPB_TRUETYPEFONT_DEV_INTERFACE_0_1, PPB_TrueTypeFont_Dev_0_1) +PROXIED_IFACE(NoAPIName, PPB_UDPSOCKET_DEV_INTERFACE_0_1, + PPB_UDPSocket_Dev_0_1) PROXIED_IFACE(NoAPIName, PPB_VAR_ARRAY_DEV_INTERFACE_0_1, PPB_VarArray_Dev_0_1) PROXIED_IFACE(NoAPIName, PPB_VAR_DICTIONARY_DEV_INTERFACE_0_1, PPB_VarDictionary_Dev_0_1) diff --git a/ppapi/thunk/ppb_udp_socket_api.h b/ppapi/thunk/ppb_udp_socket_api.h new file mode 100644 index 0000000..1368e9c --- /dev/null +++ b/ppapi/thunk/ppb_udp_socket_api.h @@ -0,0 +1,42 @@ +// 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_UDP_SOCKET_API_H_ +#define PPAPI_THUNK_PPB_UDP_SOCKET_API_H_ + +#include "base/memory/ref_counted.h" +#include "ppapi/c/dev/ppb_udp_socket_dev.h" +#include "ppapi/thunk/ppapi_thunk_export.h" + +namespace ppapi { + +class TrackedCallback; + +namespace thunk { + +class PPAPI_THUNK_EXPORT PPB_UDPSocket_API { + public: + virtual ~PPB_UDPSocket_API() {} + + virtual int32_t Bind(PP_Resource addr, + scoped_refptr<TrackedCallback> callback) = 0; + virtual PP_Resource GetBoundAddress() = 0; + virtual int32_t RecvFrom(char* buffer, + int32_t num_bytes, + PP_Resource* addr, + scoped_refptr<TrackedCallback> callback) = 0; + virtual int32_t SendTo(const char* buffer, + int32_t num_bytes, + PP_Resource addr, + scoped_refptr<TrackedCallback> callback) = 0; + virtual void Close() = 0; + virtual int32_t SetOption(PP_UDPSocket_Option_Dev name, + const PP_Var& value, + scoped_refptr<TrackedCallback> callback) = 0; +}; + +} // namespace thunk +} // namespace ppapi + +#endif // PPAPI_THUNK_PPB_UDP_SOCKET_API_H_ diff --git a/ppapi/thunk/ppb_udp_socket_dev_thunk.cc b/ppapi/thunk/ppb_udp_socket_dev_thunk.cc new file mode 100644 index 0000000..aa5165d --- /dev/null +++ b/ppapi/thunk/ppb_udp_socket_dev_thunk.cc @@ -0,0 +1,123 @@ +// 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_udp_socket_dev.idl modified Fri Jun 07 14:22:41 2013. + +#include "ppapi/c/dev/ppb_udp_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_udp_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_UDPSocket_Dev::Create()"; + EnterResourceCreation enter(instance); + if (enter.failed()) + return 0; + return enter.functions()->CreateUDPSocket(instance); +} + +PP_Bool IsUDPSocket(PP_Resource resource) { + VLOG(4) << "PPB_UDPSocket_Dev::IsUDPSocket()"; + EnterResource<PPB_UDPSocket_API> enter(resource, false); + return PP_FromBool(enter.succeeded()); +} + +int32_t Bind(PP_Resource udp_socket, + PP_Resource addr, + struct PP_CompletionCallback callback) { + VLOG(4) << "PPB_UDPSocket_Dev::Bind()"; + EnterResource<PPB_UDPSocket_API> enter(udp_socket, callback, true); + if (enter.failed()) + return enter.retval(); + return enter.SetResult(enter.object()->Bind(addr, enter.callback())); +} + +PP_Resource GetBoundAddress(PP_Resource udp_socket) { + VLOG(4) << "PPB_UDPSocket_Dev::GetBoundAddress()"; + EnterResource<PPB_UDPSocket_API> enter(udp_socket, true); + if (enter.failed()) + return 0; + return enter.object()->GetBoundAddress(); +} + +int32_t RecvFrom(PP_Resource udp_socket, + char* buffer, + int32_t num_bytes, + PP_Resource* addr, + struct PP_CompletionCallback callback) { + VLOG(4) << "PPB_UDPSocket_Dev::RecvFrom()"; + EnterResource<PPB_UDPSocket_API> enter(udp_socket, callback, true); + if (enter.failed()) + return enter.retval(); + return enter.SetResult(enter.object()->RecvFrom(buffer, + num_bytes, + addr, + enter.callback())); +} + +int32_t SendTo(PP_Resource udp_socket, + const char* buffer, + int32_t num_bytes, + PP_Resource addr, + struct PP_CompletionCallback callback) { + VLOG(4) << "PPB_UDPSocket_Dev::SendTo()"; + EnterResource<PPB_UDPSocket_API> enter(udp_socket, callback, true); + if (enter.failed()) + return enter.retval(); + return enter.SetResult(enter.object()->SendTo(buffer, + num_bytes, + addr, + enter.callback())); +} + +void Close(PP_Resource udp_socket) { + VLOG(4) << "PPB_UDPSocket_Dev::Close()"; + EnterResource<PPB_UDPSocket_API> enter(udp_socket, true); + if (enter.failed()) + return; + enter.object()->Close(); +} + +int32_t SetOption(PP_Resource udp_socket, + PP_UDPSocket_Option_Dev name, + struct PP_Var value, + struct PP_CompletionCallback callback) { + VLOG(4) << "PPB_UDPSocket_Dev::SetOption()"; + EnterResource<PPB_UDPSocket_API> enter(udp_socket, callback, true); + if (enter.failed()) + return enter.retval(); + return enter.SetResult(enter.object()->SetOption(name, + value, + enter.callback())); +} + +const PPB_UDPSocket_Dev_0_1 g_ppb_udpsocket_dev_thunk_0_1 = { + &Create, + &IsUDPSocket, + &Bind, + &GetBoundAddress, + &RecvFrom, + &SendTo, + &Close, + &SetOption +}; + +} // namespace + +const PPB_UDPSocket_Dev_0_1* GetPPB_UDPSocket_Dev_0_1_Thunk() { + return &g_ppb_udpsocket_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 a760030..70d21b9 100644 --- a/ppapi/thunk/resource_creation_api.h +++ b/ppapi/thunk/resource_creation_api.h @@ -153,6 +153,7 @@ class ResourceCreationAPI { 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 CreateUDPSocket(PP_Instance instace) = 0; virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instace) = 0; virtual PP_Resource CreateWebSocket(PP_Instance instance) = 0; virtual PP_Resource CreateX509CertificatePrivate(PP_Instance instance) = 0; diff --git a/webkit/common/plugins/ppapi/ppapi_utils.cc b/webkit/common/plugins/ppapi/ppapi_utils.cc index 8d3d830..ad82d21 100644 --- a/webkit/common/plugins/ppapi/ppapi_utils.cc +++ b/webkit/common/plugins/ppapi/ppapi_utils.cc @@ -29,6 +29,7 @@ #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/c/dev/ppb_trace_event_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" +#include "ppapi/c/dev/ppb_udp_socket_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppb_var_array_dev.h" #include "ppapi/c/dev/ppb_var_deprecated.h" diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc index 228f222..efae9b9 100644 --- a/webkit/plugins/ppapi/plugin_module.cc +++ b/webkit/plugins/ppapi/plugin_module.cc @@ -35,6 +35,7 @@ #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/c/dev/ppb_trace_event_dev.h" #include "ppapi/c/dev/ppb_truetype_font_dev.h" +#include "ppapi/c/dev/ppb_udp_socket_dev.h" #include "ppapi/c/dev/ppb_url_util_dev.h" #include "ppapi/c/dev/ppb_var_array_dev.h" #include "ppapi/c/dev/ppb_var_deprecated.h" diff --git a/webkit/plugins/ppapi/resource_creation_impl.cc b/webkit/plugins/ppapi/resource_creation_impl.cc index 640701f..4c80cb0 100644 --- a/webkit/plugins/ppapi/resource_creation_impl.cc +++ b/webkit/plugins/ppapi/resource_creation_impl.cc @@ -252,6 +252,10 @@ PP_Resource ResourceCreationImpl::CreateTCPSocketPrivate(PP_Instance instance) { return PPB_TCPSocket_Private_Impl::CreateResource(instance); } +PP_Resource ResourceCreationImpl::CreateUDPSocket(PP_Instance instance) { + return 0; // Not supported in-process. +} + PP_Resource ResourceCreationImpl::CreateUDPSocketPrivate(PP_Instance instance) { return 0; // Not supported in-process. } diff --git a/webkit/plugins/ppapi/resource_creation_impl.h b/webkit/plugins/ppapi/resource_creation_impl.h index fdf3b4d..53196ff 100644 --- a/webkit/plugins/ppapi/resource_creation_impl.h +++ b/webkit/plugins/ppapi/resource_creation_impl.h @@ -119,6 +119,7 @@ class WEBKIT_PLUGINS_EXPORT ResourceCreationImpl PP_Instance instance) OVERRIDE; virtual PP_Resource CreateTCPSocket(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE; + virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateVideoCapture(PP_Instance instance) OVERRIDE; virtual PP_Resource CreateVideoDecoder( |