Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: ppapi/proxy/udp_socket_resource_base.cc

Issue 563073002: Pepper UDP socket: buffer received packets in the plugin process to improve performance. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ppapi/proxy/udp_socket_resource_base.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/udp_socket_resource_base.h" 5 #include "ppapi/proxy/udp_socket_resource_base.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstring> 8 #include <cstring>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "ppapi/c/pp_bool.h" 11 #include "ppapi/c/pp_bool.h"
12 #include "ppapi/c/pp_completion_callback.h" 12 #include "ppapi/c/pp_completion_callback.h"
13 #include "ppapi/c/pp_errors.h" 13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/proxy/error_conversion.h" 14 #include "ppapi/proxy/error_conversion.h"
15 #include "ppapi/proxy/plugin_globals.h"
15 #include "ppapi/proxy/ppapi_messages.h" 16 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/shared_impl/socket_option_data.h" 17 #include "ppapi/shared_impl/socket_option_data.h"
17 #include "ppapi/thunk/enter.h" 18 #include "ppapi/thunk/enter.h"
18 #include "ppapi/thunk/resource_creation_api.h" 19 #include "ppapi/thunk/resource_creation_api.h"
19 20
20 namespace ppapi { 21 namespace ppapi {
21 namespace proxy { 22 namespace proxy {
22 23
23 const int32_t UDPSocketResourceBase::kMaxReadSize = 1024 * 1024; 24 const int32_t UDPSocketResourceBase::kMaxReadSize = 128 * 1024;
24 const int32_t UDPSocketResourceBase::kMaxWriteSize = 1024 * 1024; 25 const int32_t UDPSocketResourceBase::kMaxWriteSize = 128 * 1024;
25 const int32_t UDPSocketResourceBase::kMaxSendBufferSize = 26 const int32_t UDPSocketResourceBase::kMaxSendBufferSize =
26 1024 * UDPSocketResourceBase::kMaxWriteSize; 27 1024 * UDPSocketResourceBase::kMaxWriteSize;
27 const int32_t UDPSocketResourceBase::kMaxReceiveBufferSize = 28 const int32_t UDPSocketResourceBase::kMaxReceiveBufferSize =
28 1024 * UDPSocketResourceBase::kMaxReadSize; 29 1024 * UDPSocketResourceBase::kMaxReadSize;
29 30 const size_t UDPSocketResourceBase::kPluginReceiveBufferSlots = 32u;
30 31
31 UDPSocketResourceBase::UDPSocketResourceBase(Connection connection, 32 UDPSocketResourceBase::UDPSocketResourceBase(Connection connection,
32 PP_Instance instance, 33 PP_Instance instance,
33 bool private_api) 34 bool private_api)
34 : PluginResource(connection, instance), 35 : PluginResource(connection, instance),
35 private_api_(private_api), 36 private_api_(private_api),
36 bound_(false), 37 bound_(false),
37 closed_(false), 38 closed_(false),
38 read_buffer_(NULL), 39 read_buffer_(NULL),
39 bytes_to_read_(-1) { 40 bytes_to_read_(-1),
41 recvfrom_addr_resource_(NULL) {
40 recvfrom_addr_.size = 0; 42 recvfrom_addr_.size = 0;
41 memset(recvfrom_addr_.data, 0, 43 memset(recvfrom_addr_.data, 0,
42 arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data)); 44 arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data));
43 bound_addr_.size = 0; 45 bound_addr_.size = 0;
44 memset(bound_addr_.data, 0, 46 memset(bound_addr_.data, 0,
45 arraysize(bound_addr_.data) * sizeof(*bound_addr_.data)); 47 arraysize(bound_addr_.data) * sizeof(*bound_addr_.data));
46 48
47 if (private_api) 49 if (private_api)
48 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_CreatePrivate()); 50 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_CreatePrivate());
49 else 51 else
50 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_Create()); 52 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_Create());
53
54 PluginGlobals::Get()->resource_reply_thread_registrar()->HandleOnIOThread(
55 pp_resource(),
56 PpapiPluginMsg_UDPSocket_PushRecvResult::ID);
51 } 57 }
52 58
53 UDPSocketResourceBase::~UDPSocketResourceBase() { 59 UDPSocketResourceBase::~UDPSocketResourceBase() {
54 } 60 }
55 61
56 int32_t UDPSocketResourceBase::SetOptionImpl( 62 int32_t UDPSocketResourceBase::SetOptionImpl(
57 PP_UDPSocket_Option name, 63 PP_UDPSocket_Option name,
58 const PP_Var& value, 64 const PP_Var& value,
59 scoped_refptr<TrackedCallback> callback) { 65 scoped_refptr<TrackedCallback> callback) {
60 if (closed_) 66 if (closed_)
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 int32_t num_bytes, 138 int32_t num_bytes,
133 PP_Resource* addr, 139 PP_Resource* addr,
134 scoped_refptr<TrackedCallback> callback) { 140 scoped_refptr<TrackedCallback> callback) {
135 if (!buffer || num_bytes <= 0) 141 if (!buffer || num_bytes <= 0)
136 return PP_ERROR_BADARGUMENT; 142 return PP_ERROR_BADARGUMENT;
137 if (!bound_) 143 if (!bound_)
138 return PP_ERROR_FAILED; 144 return PP_ERROR_FAILED;
139 if (TrackedCallback::IsPending(recvfrom_callback_)) 145 if (TrackedCallback::IsPending(recvfrom_callback_))
140 return PP_ERROR_INPROGRESS; 146 return PP_ERROR_INPROGRESS;
141 147
142 read_buffer_ = buffer; 148 if (recv_buffers_.empty()) {
143 bytes_to_read_ = std::min(num_bytes, kMaxReadSize); 149 read_buffer_ = buffer;
144 recvfrom_callback_ = callback; 150 bytes_to_read_ = std::min(num_bytes, kMaxReadSize);
151 recvfrom_addr_resource_ = addr;
152 recvfrom_callback_ = callback;
145 153
146 // Send the request, the browser will call us back via RecvFromReply. 154 return PP_OK_COMPLETIONPENDING;
147 Call<PpapiPluginMsg_UDPSocket_RecvFromReply>( 155 } else {
148 BROWSER, 156 RecvBuffer& front = recv_buffers_.front();
149 PpapiHostMsg_UDPSocket_RecvFrom(bytes_to_read_), 157
150 base::Bind(&UDPSocketResourceBase::OnPluginMsgRecvFromReply, 158 if (num_bytes < static_cast<int32_t>(front.data.size()))
151 base::Unretained(this), addr), 159 return PP_ERROR_MESSAGE_TOO_BIG;
152 callback); 160
153 return PP_OK_COMPLETIONPENDING; 161 int32_t result = SetRecvFromOutput(front.result, front.data, front.addr,
162 buffer, num_bytes, addr);
163
164 recv_buffers_.pop();
165 Post(BROWSER, PpapiHostMsg_UDPSocket_RecvSlotAvailable());
166
167 return result;
168 }
154 } 169 }
155 170
156 PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl( 171 PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl(
157 PP_NetAddress_Private* addr) { 172 PP_NetAddress_Private* addr) {
158 if (!addr) 173 if (!addr)
159 return PP_FALSE; 174 return PP_FALSE;
160 *addr = recvfrom_addr_; 175 *addr = recvfrom_addr_;
161 return PP_TRUE; 176 return PP_TRUE;
162 } 177 }
163 178
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 Post(BROWSER, PpapiHostMsg_UDPSocket_Close()); 213 Post(BROWSER, PpapiHostMsg_UDPSocket_Close());
199 214
200 PostAbortIfNecessary(&bind_callback_); 215 PostAbortIfNecessary(&bind_callback_);
201 PostAbortIfNecessary(&recvfrom_callback_); 216 PostAbortIfNecessary(&recvfrom_callback_);
202 PostAbortIfNecessary(&sendto_callback_); 217 PostAbortIfNecessary(&sendto_callback_);
203 218
204 read_buffer_ = NULL; 219 read_buffer_ = NULL;
205 bytes_to_read_ = -1; 220 bytes_to_read_ = -1;
206 } 221 }
207 222
223 void UDPSocketResourceBase::OnReplyReceived(
224 const ResourceMessageReplyParams& params,
225 const IPC::Message& msg) {
226 PPAPI_BEGIN_MESSAGE_MAP(UDPSocketResourceBase, msg)
227 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
228 PpapiPluginMsg_UDPSocket_PushRecvResult,
229 OnPluginMsgPushRecvResult)
230 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
231 PluginResource::OnReplyReceived(params, msg))
232 PPAPI_END_MESSAGE_MAP()
233 }
234
208 void UDPSocketResourceBase::PostAbortIfNecessary( 235 void UDPSocketResourceBase::PostAbortIfNecessary(
209 scoped_refptr<TrackedCallback>* callback) { 236 scoped_refptr<TrackedCallback>* callback) {
210 if (TrackedCallback::IsPending(*callback)) 237 if (TrackedCallback::IsPending(*callback))
211 (*callback)->PostAbort(); 238 (*callback)->PostAbort();
212 } 239 }
213 240
214 void UDPSocketResourceBase::OnPluginMsgSetOptionReply( 241 void UDPSocketResourceBase::OnPluginMsgSetOptionReply(
215 scoped_refptr<TrackedCallback> callback, 242 scoped_refptr<TrackedCallback> callback,
216 const ResourceMessageReplyParams& params) { 243 const ResourceMessageReplyParams& params) {
217 if (TrackedCallback::IsPending(callback)) 244 if (TrackedCallback::IsPending(callback))
218 RunCallback(callback, params.result()); 245 RunCallback(callback, params.result());
219 } 246 }
220 247
221 void UDPSocketResourceBase::OnPluginMsgBindReply( 248 void UDPSocketResourceBase::OnPluginMsgBindReply(
222 const ResourceMessageReplyParams& params, 249 const ResourceMessageReplyParams& params,
223 const PP_NetAddress_Private& bound_addr) { 250 const PP_NetAddress_Private& bound_addr) {
224 // It is possible that |bind_callback_| is pending while |closed_| is true: 251 // It is possible that |bind_callback_| is pending while |closed_| is true:
225 // CloseImpl() has been called, but a BindReply came earlier than the task to 252 // CloseImpl() has been called, but a BindReply came earlier than the task to
226 // abort |bind_callback_|. We don't want to update |bound_| or |bound_addr_| 253 // abort |bind_callback_|. We don't want to update |bound_| or |bound_addr_|
227 // in that case. 254 // in that case.
228 if (!TrackedCallback::IsPending(bind_callback_) || closed_) 255 if (!TrackedCallback::IsPending(bind_callback_) || closed_)
229 return; 256 return;
230 257
231 if (params.result() == PP_OK) 258 if (params.result() == PP_OK)
232 bound_ = true; 259 bound_ = true;
233 bound_addr_ = bound_addr; 260 bound_addr_ = bound_addr;
234 RunCallback(bind_callback_, params.result()); 261 RunCallback(bind_callback_, params.result());
235 } 262 }
236 263
237 void UDPSocketResourceBase::OnPluginMsgRecvFromReply( 264 void UDPSocketResourceBase::OnPluginMsgPushRecvResult(
238 PP_Resource* output_addr,
239 const ResourceMessageReplyParams& params, 265 const ResourceMessageReplyParams& params,
266 int32_t result,
240 const std::string& data, 267 const std::string& data,
241 const PP_NetAddress_Private& addr) { 268 const PP_NetAddress_Private& addr) {
242 // It is possible that |recvfrom_callback_| is pending while |read_buffer_| is 269 // TODO(yzshen): Support passing in a non-const string ref, so that we can
243 // NULL: CloseImpl() has been called, but a RecvFromReply came earlier than 270 // eliminate one copy when storing the data in the buffer.
244 // the task to abort |recvfrom_callback_|. We shouldn't access the buffer in 271
245 // that case. The user may have released it. 272 DCHECK_LT(recv_buffers_.size(), kPluginReceiveBufferSlots);
246 if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) 273
274 if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) {
275 recv_buffers_.push(RecvBuffer());
276 RecvBuffer& back = recv_buffers_.back();
277 back.result = result;
278 back.data = data;
279 back.addr = addr;
280
247 return; 281 return;
248
249 int32_t result = params.result();
250 if (result == PP_OK && output_addr) {
251 thunk::EnterResourceCreationNoLock enter(pp_instance());
252 if (enter.succeeded()) {
253 *output_addr = enter.functions()->CreateNetAddressFromNetAddressPrivate(
254 pp_instance(), addr);
255 } else {
256 result = PP_ERROR_FAILED;
257 }
258 } 282 }
259 283
260 if (result == PP_OK) { 284 DCHECK_EQ(recv_buffers_.size(), 0u);
261 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); 285
262 if (!data.empty()) 286 if (bytes_to_read_ < static_cast<int32_t>(data.size())) {
263 memcpy(read_buffer_, data.c_str(), data.size()); 287 recv_buffers_.push(RecvBuffer());
288 RecvBuffer& back = recv_buffers_.back();
289 back.result = result;
290 back.data = data;
291 back.addr = addr;
292
293 result = PP_ERROR_MESSAGE_TOO_BIG;
294 } else {
295 result = SetRecvFromOutput(result, data, addr, read_buffer_, bytes_to_read_,
296 recvfrom_addr_resource_);
297 Post(BROWSER, PpapiHostMsg_UDPSocket_RecvSlotAvailable());
264 } 298 }
265 299
266 read_buffer_ = NULL; 300 read_buffer_ = NULL;
267 bytes_to_read_ = -1; 301 bytes_to_read_ = -1;
268 recvfrom_addr_ = addr; 302 recvfrom_addr_resource_ = NULL;
269 303
270 if (result == PP_OK) 304 RunCallback(recvfrom_callback_, result);
271 RunCallback(recvfrom_callback_, static_cast<int32_t>(data.size()));
272 else
273 RunCallback(recvfrom_callback_, result);
274 } 305 }
275 306
276 void UDPSocketResourceBase::OnPluginMsgSendToReply( 307 void UDPSocketResourceBase::OnPluginMsgSendToReply(
277 const ResourceMessageReplyParams& params, 308 const ResourceMessageReplyParams& params,
278 int32_t bytes_written) { 309 int32_t bytes_written) {
279 if (!TrackedCallback::IsPending(sendto_callback_)) 310 if (!TrackedCallback::IsPending(sendto_callback_))
280 return; 311 return;
281 312
282 if (params.result() == PP_OK) 313 if (params.result() == PP_OK)
283 RunCallback(sendto_callback_, bytes_written); 314 RunCallback(sendto_callback_, bytes_written);
284 else 315 else
285 RunCallback(sendto_callback_, params.result()); 316 RunCallback(sendto_callback_, params.result());
286 } 317 }
287 318
288 void UDPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback, 319 void UDPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback,
289 int32_t pp_result) { 320 int32_t pp_result) {
290 callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result, 321 callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result,
291 private_api_)); 322 private_api_));
292 } 323 }
293 324
325 int32_t UDPSocketResourceBase::SetRecvFromOutput(
326 int32_t browser_result,
327 const std::string& data,
328 const PP_NetAddress_Private& addr,
329 char* output_buffer,
330 int32_t num_bytes,
331 PP_Resource* output_addr) {
332 DCHECK_GE(num_bytes, static_cast<int32_t>(data.size()));
333
334 int32_t result = browser_result;
335 if (result == PP_OK && output_addr) {
336 thunk::EnterResourceCreationNoLock enter(pp_instance());
337 if (enter.succeeded()) {
338 *output_addr = enter.functions()->CreateNetAddressFromNetAddressPrivate(
339 pp_instance(), addr);
340 } else {
341 result = PP_ERROR_FAILED;
342 }
343 }
344
345 if (result == PP_OK && !data.empty())
346 memcpy(output_buffer, data.c_str(), data.size());
Tom Sepez 2014/09/12 01:28:14 The DCHECK that output_buffer is big enough to han
yzshen1 2014/09/12 16:49:17 This is a private method of the class, and all cal
347
348 recvfrom_addr_ = addr;
349
350 return result == PP_OK ? static_cast<int32_t>(data.size()) : result;
351 }
352
294 } // namespace proxy 353 } // namespace proxy
295 } // namespace ppapi 354 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/udp_socket_resource_base.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698