diff options
author | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-27 12:19:50 +0000 |
---|---|---|
committer | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-27 12:19:50 +0000 |
commit | 7c65124882899919bbd302842095758cb5804bde (patch) | |
tree | bb926631d2d92903780729a1cfe9e409b4288a60 | |
parent | cdbea94e52b0a9fb0590d1e219f764ca44836d37 (diff) | |
download | chromium_src-7c65124882899919bbd302842095758cb5804bde.zip chromium_src-7c65124882899919bbd302842095758cb5804bde.tar.gz chromium_src-7c65124882899919bbd302842095758cb5804bde.tar.bz2 |
Implemented queued UDP SendTo/RecvFrom requests.
BUG=154338
TEST=browser_tests:*UDPSocketPrivate*
Review URL: https://chromiumcodereview.appspot.com/12316095
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184934 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/test/ppapi/ppapi_browsertest.cc | 4 | ||||
-rw-r--r-- | content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc | 124 | ||||
-rw-r--r-- | content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.h | 40 | ||||
-rw-r--r-- | ppapi/proxy/udp_socket_private_resource.cc | 56 | ||||
-rw-r--r-- | ppapi/proxy/udp_socket_private_resource.h | 22 | ||||
-rw-r--r-- | ppapi/tests/test_udp_socket_private.cc | 143 | ||||
-rw-r--r-- | ppapi/tests/test_udp_socket_private.h | 7 |
7 files changed, 321 insertions, 75 deletions
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index f575df5..21228ef 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc @@ -294,12 +294,16 @@ TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(UDPSocketPrivate_ConnectFailure) TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(UDPSocketPrivate_Broadcast) #endif // !defined(OS_MACOSX) TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(UDPSocketPrivate_SetSocketFeatureErrors) +TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(UDPSocketPrivate_SequentialRequests) +TEST_PPAPI_OUT_OF_PROCESS_VIA_HTTP(UDPSocketPrivate_QueuedRequests) TEST_PPAPI_NACL(UDPSocketPrivate_Connect) TEST_PPAPI_NACL(UDPSocketPrivate_ConnectFailure) #if !defined(OS_MACOSX) TEST_PPAPI_NACL(UDPSocketPrivate_Broadcast) #endif // !defined(OS_MACOSX) TEST_PPAPI_NACL(UDPSocketPrivate_SetSocketFeatureErrors) +TEST_PPAPI_NACL(UDPSocketPrivate_SequentialRequests) +TEST_PPAPI_NACL(UDPSocketPrivate_QueuedRequests) TEST_PPAPI_NACL_DISALLOWED_SOCKETS(HostResolverPrivateDisallowed) TEST_PPAPI_NACL_DISALLOWED_SOCKETS(TCPServerSocketPrivateDisallowed) diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc b/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc index a6261dd..41b0620 100644 --- a/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.cc @@ -15,7 +15,6 @@ #include "content/public/common/process_type.h" #include "content/public/common/socket_permission_request.h" #include "ipc/ipc_message_macros.h" -#include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/udp/udp_server_socket.h" #include "ppapi/c/pp_errors.h" @@ -48,12 +47,28 @@ bool CanUseSocketAPIs(const SocketPermissionRequest& request, } // namespace +PepperUDPSocketPrivateMessageFilter::IORequest::IORequest( + const scoped_refptr<net::IOBuffer>& buffer, + int32_t buffer_size, + const linked_ptr<net::IPEndPoint>& end_point, + const ppapi::host::ReplyMessageContext& context) + : buffer(buffer), + buffer_size(buffer_size), + end_point(end_point), + context(context) { +} + +PepperUDPSocketPrivateMessageFilter::IORequest::~IORequest() { +} + PepperUDPSocketPrivateMessageFilter::PepperUDPSocketPrivateMessageFilter( BrowserPpapiHostImpl* host, PP_Instance instance) : allow_address_reuse_(false), allow_broadcast_(false), closed_(false), + recvfrom_state_(IO_STATE_IDLE), + sendto_state_(IO_STATE_IDLE), plugin_process_type_(host->plugin_process_type()), render_process_id_(0), render_view_id_(0) { @@ -161,20 +176,18 @@ int32_t PepperUDPSocketPrivateMessageFilter::OnMsgRecvFrom( DCHECK(socket_.get()); DCHECK(!closed_); - if (recvfrom_buffer_.get()) - return PP_ERROR_INPROGRESS; if (num_bytes > ppapi::proxy::UDPSocketPrivateResource::kMaxReadSize) { // |num_bytes| value is checked on the plugin side. NOTREACHED(); num_bytes = ppapi::proxy::UDPSocketPrivateResource::kMaxReadSize; } - recvfrom_buffer_ = new net::IOBuffer(num_bytes); - int result = socket_->RecvFrom( - recvfrom_buffer_, num_bytes, &recvfrom_address_, - base::Bind(&PepperUDPSocketPrivateMessageFilter::OnRecvFromCompleted, - this, context->MakeReplyMessageContext())); - if (result != net::ERR_IO_PENDING) - OnRecvFromCompleted(context->MakeReplyMessageContext(), result); + scoped_refptr<net::IOBuffer> recvfrom_buffer(new net::IOBuffer(num_bytes)); + linked_ptr<net::IPEndPoint> end_point(new net::IPEndPoint()); + recvfrom_requests_.push(IORequest(recvfrom_buffer, + num_bytes, + end_point, + context->MakeReplyMessageContext())); + RecvFromInternal(); return PP_OK_COMPLETIONPENDING; } @@ -207,6 +220,38 @@ int32_t PepperUDPSocketPrivateMessageFilter::OnMsgClose( return PP_OK; } +void PepperUDPSocketPrivateMessageFilter::RecvFromInternal() { + if (recvfrom_requests_.empty() || recvfrom_state_ == IO_STATE_IN_PROCESS) + return; + DCHECK(recvfrom_state_ == IO_STATE_IDLE); + recvfrom_state_ = IO_STATE_IN_PROCESS; + const IORequest& request = recvfrom_requests_.front(); + int result = socket_->RecvFrom( + request.buffer.get(), + static_cast<int>(request.buffer_size), + request.end_point.get(), + base::Bind(&PepperUDPSocketPrivateMessageFilter::OnRecvFromCompleted, + this, request)); + if (result != net::ERR_IO_PENDING) + OnRecvFromCompleted(request, result); +} + +void PepperUDPSocketPrivateMessageFilter::SendToInternal() { + if (sendto_requests_.empty() || sendto_state_ == IO_STATE_IN_PROCESS) + return; + DCHECK(sendto_state_ == IO_STATE_IDLE); + sendto_state_ = IO_STATE_IN_PROCESS; + const IORequest& request = sendto_requests_.front(); + int result = socket_->SendTo( + request.buffer.get(), + static_cast<int>(request.buffer_size), + *request.end_point.get(), + base::Bind(&PepperUDPSocketPrivateMessageFilter::OnSendToCompleted, + this, request)); + if (result != net::ERR_IO_PENDING) + OnSendToCompleted(request, result); +} + void PepperUDPSocketPrivateMessageFilter::DoBind( const ppapi::host::ReplyMessageContext& context, const PP_NetAddress_Private& addr) { @@ -251,11 +296,6 @@ void PepperUDPSocketPrivateMessageFilter::DoSendTo( DCHECK(socket_.get()); DCHECK(!closed_); - if (sendto_buffer_.get()) { - SendSendToError(context, PP_ERROR_INPROGRESS); - return; - } - if (data.empty() || data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) { SendSendToError(context, PP_ERROR_BADARGUMENT); @@ -269,8 +309,10 @@ void PepperUDPSocketPrivateMessageFilter::DoSendTo( num_bytes = static_cast<size_t>( ppapi::proxy::UDPSocketPrivateResource::kMaxWriteSize); } - sendto_buffer_ = new net::IOBufferWithSize(num_bytes); - memcpy(sendto_buffer_->data(), data.data(), num_bytes); + + scoped_refptr<net::IOBuffer> sendto_buffer( + new net::IOBufferWithSize(num_bytes)) ; + memcpy(sendto_buffer->data(), data.data(), num_bytes); net::IPAddressNumber address; int port; @@ -278,13 +320,13 @@ void PepperUDPSocketPrivateMessageFilter::DoSendTo( SendSendToError(context, PP_ERROR_FAILED); return; } + linked_ptr<net::IPEndPoint> end_point(new net::IPEndPoint(address, port)); - int result = socket_->SendTo( - sendto_buffer_, sendto_buffer_->size(), net::IPEndPoint(address, port), - base::Bind(&PepperUDPSocketPrivateMessageFilter::OnSendToCompleted, this, - context)); - if (result != net::ERR_IO_PENDING) - OnSendToCompleted(context, result); + sendto_requests_.push(IORequest(sendto_buffer, + static_cast<int32_t>(num_bytes), + end_point, + context)); + SendToInternal(); } void PepperUDPSocketPrivateMessageFilter::Close() { @@ -295,38 +337,46 @@ void PepperUDPSocketPrivateMessageFilter::Close() { } void PepperUDPSocketPrivateMessageFilter::OnRecvFromCompleted( - const ppapi::host::ReplyMessageContext& context, + const IORequest& request, int32_t result) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK(recvfrom_buffer_.get()); + DCHECK(request.buffer.get()); + DCHECK(request.end_point.get()); // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private, // to send back. PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; if (result < 0 || !NetAddressPrivateImpl::IPEndPointToNetAddress( - recvfrom_address_.address(), - recvfrom_address_.port(), + request.end_point->address(), + request.end_point->port(), &addr)) { - SendRecvFromError(context, PP_ERROR_FAILED); + SendRecvFromError(request.context, PP_ERROR_FAILED); } else { - SendRecvFromReply(context, PP_OK, - std::string(recvfrom_buffer_->data(), result), addr); + SendRecvFromReply(request.context, PP_OK, + std::string(request.buffer->data(), result), addr); } - - recvfrom_buffer_ = NULL; + // Take out |request| from |recvfrom_requests_| queue. + recvfrom_requests_.pop(); + recvfrom_state_ = IO_STATE_IDLE; + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&PepperUDPSocketPrivateMessageFilter::RecvFromInternal, this)); } void PepperUDPSocketPrivateMessageFilter::OnSendToCompleted( - const ppapi::host::ReplyMessageContext& context, + const IORequest& request, int32_t result) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK(sendto_buffer_.get()); + DCHECK(request.buffer.get()); if (result < 0) - SendSendToError(context, PP_ERROR_FAILED); + SendSendToError(request.context, PP_ERROR_FAILED); else - SendSendToReply(context, PP_OK, result); - sendto_buffer_ = NULL; + SendSendToReply(request.context, PP_OK, result); + // Take out |request| from |sendto_requests_| queue. + sendto_requests_.pop(); + sendto_state_ = IO_STATE_IDLE; + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&PepperUDPSocketPrivateMessageFilter::SendToInternal, this)); } void PepperUDPSocketPrivateMessageFilter::SendBindReply( diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.h b/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.h index eb62a1f..7ae6488 100644 --- a/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.h +++ b/content/browser/renderer_host/pepper/pepper_udp_socket_private_message_filter.h @@ -5,16 +5,19 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_UDP_SOCKET_PRIVATE_MESSAGE_FILTER_H_ #define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_UDP_SOCKET_PRIVATE_MESSAGE_FILTER_H_ +#include <queue> #include <string> #include "base/basictypes.h" #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" #include "content/public/common/process_type.h" #include "net/base/completion_callback.h" +#include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_stdint.h" @@ -23,8 +26,6 @@ struct PP_NetAddress_Private; namespace net { -class IOBuffer; -class IOBufferWithSize; class UDPServerSocket; } @@ -49,6 +50,24 @@ class CONTENT_EXPORT PepperUDPSocketPrivateMessageFilter virtual ~PepperUDPSocketPrivateMessageFilter(); private: + enum IOState { + IO_STATE_IDLE = 0, + IO_STATE_IN_PROCESS + }; + + struct IORequest { + IORequest(const scoped_refptr<net::IOBuffer>& buffer, + int32_t buffer_size, + const linked_ptr<net::IPEndPoint>& end_point, + const ppapi::host::ReplyMessageContext& context); + ~IORequest(); + + scoped_refptr<net::IOBuffer> buffer; + int32_t buffer_size; + linked_ptr<net::IPEndPoint> end_point; + ppapi::host::ReplyMessageContext context; + }; + // ppapi::host::ResourceMessageFilter overrides. virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage( const IPC::Message& message) OVERRIDE; @@ -69,6 +88,9 @@ class CONTENT_EXPORT PepperUDPSocketPrivateMessageFilter const PP_NetAddress_Private& addr); int32_t OnMsgClose(const ppapi::host::HostMessageContext* context); + void RecvFromInternal(); + void SendToInternal(); + void DoBind(const ppapi::host::ReplyMessageContext& context, const PP_NetAddress_Private& addr); void DoSendTo(const ppapi::host::ReplyMessageContext& context, @@ -76,10 +98,8 @@ class CONTENT_EXPORT PepperUDPSocketPrivateMessageFilter const PP_NetAddress_Private& addr); void Close(); - void OnRecvFromCompleted(const ppapi::host::ReplyMessageContext& context, - int32_t result); - void OnSendToCompleted(const ppapi::host::ReplyMessageContext& context, - int32_t result); + void OnRecvFromCompleted(const IORequest& request, int32_t result); + void OnSendToCompleted(const IORequest& request, int32_t result); void SendBindReply(const ppapi::host::ReplyMessageContext& context, int32_t result, @@ -105,10 +125,10 @@ class CONTENT_EXPORT PepperUDPSocketPrivateMessageFilter scoped_ptr<net::UDPServerSocket> socket_; bool closed_; - scoped_refptr<net::IOBuffer> recvfrom_buffer_; - scoped_refptr<net::IOBufferWithSize> sendto_buffer_; - - net::IPEndPoint recvfrom_address_; + std::queue<IORequest> recvfrom_requests_; + std::queue<IORequest> sendto_requests_; + IOState recvfrom_state_; + IOState sendto_state_; ProcessType plugin_process_type_; int render_process_id_; diff --git a/ppapi/proxy/udp_socket_private_resource.cc b/ppapi/proxy/udp_socket_private_resource.cc index 608fc00..ea08b7e 100644 --- a/ppapi/proxy/udp_socket_private_resource.cc +++ b/ppapi/proxy/udp_socket_private_resource.cc @@ -24,9 +24,7 @@ UDPSocketPrivateResource::UDPSocketPrivateResource(Connection connection, PP_Instance instance) : PluginResource(connection, instance), bound_(false), - closed_(false), - read_buffer_(NULL), - bytes_to_read_(-1) { + closed_(false) { recvfrom_addr_.size = 0; memset(recvfrom_addr_.data, 0, arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data)); @@ -98,15 +96,13 @@ int32_t UDPSocketPrivateResource::RecvFrom( 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; + recvfrom_requests_.push(RecvFromRequest(callback, + buffer, + std::min(num_bytes, kMaxReadSize))); // Send the request, the browser will call us back via RecvFromReply. - SendRecvFrom(bytes_to_read_); + SendRecvFrom(num_bytes); return PP_OK_COMPLETIONPENDING; } @@ -133,13 +129,11 @@ int32_t UDPSocketPrivateResource::SendTo( 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; + sendto_callbacks_.push(callback); // Send the request, the browser will call us back via SendToReply. SendSendTo(std::string(buffer, num_bytes), *addr); @@ -156,8 +150,15 @@ void UDPSocketPrivateResource::Close() { SendClose(); PostAbortIfNecessary(&bind_callback_); - PostAbortIfNecessary(&recvfrom_callback_); - PostAbortIfNecessary(&sendto_callback_); + while (!recvfrom_requests_.empty()) { + RecvFromRequest& request = recvfrom_requests_.front(); + PostAbortIfNecessary(&request.callback); + recvfrom_requests_.pop(); + } + while (!sendto_callbacks_.empty()) { + PostAbortIfNecessary(&sendto_callbacks_.front()); + sendto_callbacks_.pop(); + } } void UDPSocketPrivateResource::SendBoolSocketFeature(int32_t name, bool value) { @@ -215,37 +216,44 @@ void UDPSocketPrivateResource::OnPluginMsgRecvFromReply( const ResourceMessageReplyParams& params, const std::string& data, const PP_NetAddress_Private& addr) { - if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) { + if (recvfrom_requests_.empty()) + return; + RecvFromRequest request = recvfrom_requests_.front(); + recvfrom_requests_.pop(); + if (!TrackedCallback::IsPending(request.callback) || !request.buffer) { NOTREACHED(); return; } bool succeeded = (params.result() == PP_OK); if (succeeded) { - CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); + CHECK_LE(static_cast<int32_t>(data.size()), request.num_bytes); if (!data.empty()) - memcpy(read_buffer_, data.c_str(), data.size()); + memcpy(request.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())); + request.callback->Run(static_cast<int32_t>(data.size())); else - recvfrom_callback_->Run(params.result()); + request.callback->Run(params.result()); } void UDPSocketPrivateResource::OnPluginMsgSendToReply( const ResourceMessageReplyParams& params, int32_t bytes_written) { - if (!TrackedCallback::IsPending(sendto_callback_)) { + if (sendto_callbacks_.empty()) + return; + scoped_refptr<TrackedCallback> callback = sendto_callbacks_.front(); + sendto_callbacks_.pop(); + if (!TrackedCallback::IsPending(callback)) { NOTREACHED(); return; } if (params.result() == PP_OK) - sendto_callback_->Run(bytes_written); + callback->Run(bytes_written); else - sendto_callback_->Run(params.result()); + callback->Run(params.result()); } } // namespace proxy diff --git a/ppapi/proxy/udp_socket_private_resource.h b/ppapi/proxy/udp_socket_private_resource.h index 6403f6b..e72f44e 100644 --- a/ppapi/proxy/udp_socket_private_resource.h +++ b/ppapi/proxy/udp_socket_private_resource.h @@ -5,6 +5,8 @@ #ifndef PPAPI_PROXY_UDP_SOCKET_PRIVATE_RESOURCE_H_ #define PPAPI_PROXY_UDP_SOCKET_PRIVATE_RESOURCE_H_ +#include <queue> + #include "base/basictypes.h" #include "base/compiler_specific.h" #include "ppapi/proxy/plugin_resource.h" @@ -51,6 +53,20 @@ class PPAPI_PROXY_EXPORT UDPSocketPrivateResource virtual void Close() OVERRIDE; private: + struct RecvFromRequest { + RecvFromRequest(scoped_refptr<TrackedCallback> callback, + char* buffer, + int32_t num_bytes) + : callback(callback), + buffer(buffer), + num_bytes(num_bytes) { + } + + scoped_refptr<TrackedCallback> callback; + char* buffer; + int32_t num_bytes; + }; + void PostAbortIfNecessary(scoped_refptr<TrackedCallback>* callback); void SendBoolSocketFeature(int32_t name, bool value); @@ -73,11 +89,9 @@ class PPAPI_PROXY_EXPORT UDPSocketPrivateResource 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_; + std::queue<RecvFromRequest> recvfrom_requests_; + std::queue<scoped_refptr<TrackedCallback> > sendto_callbacks_; PP_NetAddress_Private recvfrom_addr_; PP_NetAddress_Private bound_addr_; diff --git a/ppapi/tests/test_udp_socket_private.cc b/ppapi/tests/test_udp_socket_private.cc index 4680ff2..b91f1a9 100644 --- a/ppapi/tests/test_udp_socket_private.cc +++ b/ppapi/tests/test_udp_socket_private.cc @@ -20,6 +20,17 @@ namespace { const uint16_t kPortScanFrom = 1024; const uint16_t kPortScanTo = 4096; +const size_t kEnglishAlphabetSize = 'z' - 'a' + 1; + +// 4K datagrams for sendto/recvfrom benchmarks. +const size_t kBenchmarkMessageSize = 1u << 12; + +// Maximum number of datagrams for sendto/recvfrom benchmarks. +const size_t kBenchmarkMaxNumMessages = 1u << 12; + +// Assuming that system buffer size for UDP sockets is at least 32K. +const size_t kUDPBufferSize = 32768; + } // namespace TestUDPSocketPrivate::TestUDPSocketPrivate( @@ -58,6 +69,8 @@ void TestUDPSocketPrivate::RunTests(const std::string& filter) { RUN_TEST_FORCEASYNC_AND_NOT(ConnectFailure, filter); RUN_TEST_FORCEASYNC_AND_NOT(Broadcast, filter); RUN_TEST_FORCEASYNC_AND_NOT(SetSocketFeatureErrors, filter); + RUN_TEST_FORCEASYNC_AND_NOT(QueuedRequests, filter); + RUN_TEST_FORCEASYNC_AND_NOT(SequentialRequests, filter); } std::string TestUDPSocketPrivate::GetLocalAddress( @@ -182,6 +195,118 @@ std::string TestUDPSocketPrivate::PassMessage(pp::UDPSocketPrivate* target, PASS(); } +std::string TestUDPSocketPrivate::BenchmarkQueuedRequests(size_t num_messages, + size_t message_size) { + pp::UDPSocketPrivate server_socket(instance_), client_socket(instance_); + PP_NetAddress_Private server_address, client_address; + + ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket, + &server_address)); + ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket, + &client_address)); + + std::vector<std::string> messages(num_messages); + for (size_t i = 0; i < num_messages; ++i) + messages[i].resize(message_size, 'a' + i % kEnglishAlphabetSize); + + std::vector<TestCompletionCallback*> sendto_callbacks(num_messages); + std::vector<int32_t> sendto_rv(num_messages); + + std::vector<std::vector<char> > buffers(num_messages); + std::vector<TestCompletionCallback*> recvfrom_callbacks(num_messages); + std::vector<int32_t> recvfrom_rv(num_messages); + + for (size_t i = 0; i < num_messages; ++i) { + sendto_callbacks[i] = new TestCompletionCallback(instance_->pp_instance(), + force_async_); + recvfrom_callbacks[i] = new TestCompletionCallback(instance_->pp_instance(), + force_async_); + } + + for (size_t i = 0; i < num_messages; ++i) { + buffers[i].resize(messages[i].size()); + recvfrom_rv[i] = server_socket.RecvFrom(&buffers[i][0], + messages[i].size(), + *recvfrom_callbacks[i]); + if (force_async_ && recvfrom_rv[i] != PP_OK_COMPLETIONPENDING) { + return ReportError("PPB_UDPSocket_Private::RecvFrom force_async", + recvfrom_rv[i]); + } + } + + size_t num_sent = 0, num_read = 0; + while (num_sent < num_messages || num_read < num_messages) { + if ((num_sent < num_read || + (num_sent - num_read) * message_size < kUDPBufferSize) && + (num_sent < num_messages)) { + sendto_rv[num_sent] = client_socket.SendTo(messages[num_sent].c_str(), + messages[num_sent].size(), + &server_address, + *sendto_callbacks[num_sent]); + if (force_async_ && sendto_rv[num_sent] != PP_OK_COMPLETIONPENDING) { + return ReportError("PPB_UDPSocket_Private::SendTo force_async", + sendto_rv[num_sent]); + } + ++num_sent; + } else if (num_read < num_messages) { + if (recvfrom_rv[num_read] == PP_OK_COMPLETIONPENDING) + recvfrom_rv[num_read] = recvfrom_callbacks[num_read]->WaitForResult(); + if (recvfrom_rv[num_read] < 0 || + messages[num_read].size() != + static_cast<size_t>(recvfrom_rv[num_read])) { + return ReportError("PPB_UDPSocket_Private::RecvFrom", + recvfrom_rv[num_read]); + } + ++num_read; + } + } + + for (size_t i = 0; i < num_messages; ++i) { + if (sendto_rv[i] == PP_OK_COMPLETIONPENDING) + sendto_rv[i] = sendto_callbacks[i]->WaitForResult(); + if (sendto_rv[i] < 0 || + messages[i].size() != static_cast<size_t>(sendto_rv[i])) { + return ReportError("PPB_UDPSocket_Private::SendTo", sendto_rv[i]); + } + ASSERT_EQ(messages[i], std::string(buffers[i].begin(), buffers[i].end())); + } + + for (size_t i = 0; i < num_messages; ++i) { + delete sendto_callbacks[i]; + delete recvfrom_callbacks[i]; + } + + server_socket.Close(); + client_socket.Close(); + PASS(); +} + +std::string TestUDPSocketPrivate::BenchmarkSequentialRequests( + size_t num_messages, + size_t message_size) { + pp::UDPSocketPrivate server_socket(instance_), client_socket(instance_); + PP_NetAddress_Private server_address, client_address; + + ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket, + &server_address)); + ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket, + &client_address)); + std::vector<std::string> messages(num_messages); + for (size_t i = 0; i < num_messages; ++i) + messages[i].resize(message_size, 'a' + i % kEnglishAlphabetSize); + + for (size_t i = 0; i < num_messages; ++i) { + ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket, + &client_socket, + &server_address, + messages[i])); + } + + server_socket.Close(); + client_socket.Close(); + PASS(); +} + std::string TestUDPSocketPrivate::TestConnect() { pp::UDPSocketPrivate server_socket(instance_), client_socket(instance_); PP_NetAddress_Private server_address, client_address; @@ -274,3 +399,21 @@ std::string TestUDPSocketPrivate::TestSetSocketFeatureErrors() { ASSERT_EQ(PP_ERROR_BADARGUMENT, rv); PASS(); } + +std::string TestUDPSocketPrivate::TestSequentialRequests() { + for (size_t num_messages = 1u << 8; + num_messages <= kBenchmarkMaxNumMessages; num_messages <<= 1) { + ASSERT_SUBTEST_SUCCESS(BenchmarkSequentialRequests(num_messages, + kBenchmarkMessageSize)); + } + PASS(); +} + +std::string TestUDPSocketPrivate::TestQueuedRequests() { + for (size_t num_messages = 1u << 8; + num_messages <= kBenchmarkMaxNumMessages; num_messages <<= 1) { + ASSERT_SUBTEST_SUCCESS(BenchmarkQueuedRequests(num_messages, + kBenchmarkMessageSize)); + } + PASS(); +} diff --git a/ppapi/tests/test_udp_socket_private.h b/ppapi/tests/test_udp_socket_private.h index e4a23c9..82db100 100644 --- a/ppapi/tests/test_udp_socket_private.h +++ b/ppapi/tests/test_udp_socket_private.h @@ -37,10 +37,17 @@ class TestUDPSocketPrivate : public TestCase { PP_NetAddress_Private* address, const std::string& message); + std::string BenchmarkQueuedRequests(size_t num_messages, + size_t message_size); + std::string BenchmarkSequentialRequests(size_t num_messages, + size_t message_size); + std::string TestConnect(); std::string TestConnectFailure(); std::string TestBroadcast(); std::string TestSetSocketFeatureErrors(); + std::string TestQueuedRequests(); + std::string TestSequentialRequests(); std::string host_; uint16_t port_; |