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

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 PpapiPluginMsg_UDPSocket_PushRecvResult::ID);
51 } 56 }
52 57
53 UDPSocketResourceBase::~UDPSocketResourceBase() { 58 UDPSocketResourceBase::~UDPSocketResourceBase() {
54 } 59 }
55 60
56 int32_t UDPSocketResourceBase::SetOptionImpl( 61 int32_t UDPSocketResourceBase::SetOptionImpl(
57 PP_UDPSocket_Option name, 62 PP_UDPSocket_Option name,
58 const PP_Var& value, 63 const PP_Var& value,
59 scoped_refptr<TrackedCallback> callback) { 64 scoped_refptr<TrackedCallback> callback) {
60 if (closed_) 65 if (closed_)
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 int32_t num_bytes, 137 int32_t num_bytes,
133 PP_Resource* addr, 138 PP_Resource* addr,
134 scoped_refptr<TrackedCallback> callback) { 139 scoped_refptr<TrackedCallback> callback) {
135 if (!buffer || num_bytes <= 0) 140 if (!buffer || num_bytes <= 0)
136 return PP_ERROR_BADARGUMENT; 141 return PP_ERROR_BADARGUMENT;
137 if (!bound_) 142 if (!bound_)
138 return PP_ERROR_FAILED; 143 return PP_ERROR_FAILED;
139 if (TrackedCallback::IsPending(recvfrom_callback_)) 144 if (TrackedCallback::IsPending(recvfrom_callback_))
140 return PP_ERROR_INPROGRESS; 145 return PP_ERROR_INPROGRESS;
141 146
142 read_buffer_ = buffer; 147 if (recv_buffers_.empty()) {
143 bytes_to_read_ = std::min(num_bytes, kMaxReadSize); 148 read_buffer_ = buffer;
144 recvfrom_callback_ = callback; 149 bytes_to_read_ = std::min(num_bytes, kMaxReadSize);
150 recvfrom_addr_resource_ = addr;
151 recvfrom_callback_ = callback;
145 152
146 // Send the request, the browser will call us back via RecvFromReply. 153 return PP_OK_COMPLETIONPENDING;
147 Call<PpapiPluginMsg_UDPSocket_RecvFromReply>( 154 } else {
148 BROWSER, 155 RecvBuffer& front = recv_buffers_.front();
149 PpapiHostMsg_UDPSocket_RecvFrom(bytes_to_read_), 156
150 base::Bind(&UDPSocketResourceBase::OnPluginMsgRecvFromReply, 157 if (num_bytes < static_cast<int32_t>(front.data.size()))
151 base::Unretained(this), addr), 158 return PP_ERROR_MESSAGE_TOO_BIG;
152 callback); 159
153 return PP_OK_COMPLETIONPENDING; 160 int32_t result = SetRecvFromOutput(front.result, front.data, front.addr,
161 buffer, num_bytes, addr);
162
163 recv_buffers_.pop();
164 Post(BROWSER, PpapiHostMsg_UDPSocket_RecvSlotAvailable());
165
166 return result;
167 }
154 } 168 }
155 169
156 PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl( 170 PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl(
157 PP_NetAddress_Private* addr) { 171 PP_NetAddress_Private* addr) {
158 if (!addr) 172 if (!addr)
159 return PP_FALSE; 173 return PP_FALSE;
160 *addr = recvfrom_addr_; 174 *addr = recvfrom_addr_;
161 return PP_TRUE; 175 return PP_TRUE;
162 } 176 }
163 177
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 Post(BROWSER, PpapiHostMsg_UDPSocket_Close()); 212 Post(BROWSER, PpapiHostMsg_UDPSocket_Close());
199 213
200 PostAbortIfNecessary(&bind_callback_); 214 PostAbortIfNecessary(&bind_callback_);
201 PostAbortIfNecessary(&recvfrom_callback_); 215 PostAbortIfNecessary(&recvfrom_callback_);
202 PostAbortIfNecessary(&sendto_callback_); 216 PostAbortIfNecessary(&sendto_callback_);
203 217
204 read_buffer_ = NULL; 218 read_buffer_ = NULL;
205 bytes_to_read_ = -1; 219 bytes_to_read_ = -1;
206 } 220 }
207 221
222 void UDPSocketResourceBase::OnReplyReceived(
223 const ResourceMessageReplyParams& params,
224 const IPC::Message& msg) {
225 PPAPI_BEGIN_MESSAGE_MAP(UDPSocketResourceBase, msg)
226 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
227 PpapiPluginMsg_UDPSocket_PushRecvResult,
228 OnPluginMsgPushRecvResult)
229 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
230 PluginResource::OnReplyReceived(params, msg))
231 PPAPI_END_MESSAGE_MAP()
232 }
233
208 void UDPSocketResourceBase::PostAbortIfNecessary( 234 void UDPSocketResourceBase::PostAbortIfNecessary(
209 scoped_refptr<TrackedCallback>* callback) { 235 scoped_refptr<TrackedCallback>* callback) {
210 if (TrackedCallback::IsPending(*callback)) 236 if (TrackedCallback::IsPending(*callback))
211 (*callback)->PostAbort(); 237 (*callback)->PostAbort();
212 } 238 }
213 239
214 void UDPSocketResourceBase::OnPluginMsgSetOptionReply( 240 void UDPSocketResourceBase::OnPluginMsgSetOptionReply(
215 scoped_refptr<TrackedCallback> callback, 241 scoped_refptr<TrackedCallback> callback,
216 const ResourceMessageReplyParams& params) { 242 const ResourceMessageReplyParams& params) {
217 if (TrackedCallback::IsPending(callback)) 243 if (TrackedCallback::IsPending(callback))
218 RunCallback(callback, params.result()); 244 RunCallback(callback, params.result());
219 } 245 }
220 246
221 void UDPSocketResourceBase::OnPluginMsgBindReply( 247 void UDPSocketResourceBase::OnPluginMsgBindReply(
222 const ResourceMessageReplyParams& params, 248 const ResourceMessageReplyParams& params,
223 const PP_NetAddress_Private& bound_addr) { 249 const PP_NetAddress_Private& bound_addr) {
224 // It is possible that |bind_callback_| is pending while |closed_| is true: 250 // 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 251 // 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_| 252 // abort |bind_callback_|. We don't want to update |bound_| or |bound_addr_|
227 // in that case. 253 // in that case.
228 if (!TrackedCallback::IsPending(bind_callback_) || closed_) 254 if (!TrackedCallback::IsPending(bind_callback_) || closed_)
229 return; 255 return;
230 256
231 if (params.result() == PP_OK) 257 if (params.result() == PP_OK)
232 bound_ = true; 258 bound_ = true;
233 bound_addr_ = bound_addr; 259 bound_addr_ = bound_addr;
234 RunCallback(bind_callback_, params.result()); 260 RunCallback(bind_callback_, params.result());
235 } 261 }
236 262
237 void UDPSocketResourceBase::OnPluginMsgRecvFromReply( 263 void UDPSocketResourceBase::OnPluginMsgPushRecvResult(
238 PP_Resource* output_addr,
239 const ResourceMessageReplyParams& params, 264 const ResourceMessageReplyParams& params,
265 int32_t result,
240 const std::string& data, 266 const std::string& data,
241 const PP_NetAddress_Private& addr) { 267 const PP_NetAddress_Private& addr) {
242 // It is possible that |recvfrom_callback_| is pending while |read_buffer_| is 268 // 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 269 // eliminate one copy when storing the data in the buffer.
244 // the task to abort |recvfrom_callback_|. We shouldn't access the buffer in 270
245 // that case. The user may have released it. 271 DCHECK_LT(recv_buffers_.size(), kPluginReceiveBufferSlots);
246 if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) 272
273 if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) {
274 recv_buffers_.push(RecvBuffer());
275 RecvBuffer& back = recv_buffers_.back();
276 back.result = result;
277 back.data = data;
278 back.addr = addr;
279
247 return; 280 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 } 281 }
259 282
260 if (result == PP_OK) { 283 DCHECK_EQ(recv_buffers_.size(), 0u);
261 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); 284
262 if (!data.empty()) 285 if (bytes_to_read_ < static_cast<int32_t>(data.size())) {
263 memcpy(read_buffer_, data.c_str(), data.size()); 286 recv_buffers_.push(RecvBuffer());
287 RecvBuffer& back = recv_buffers_.back();
288 back.result = result;
289 back.data = data;
290 back.addr = addr;
291
292 result = PP_ERROR_MESSAGE_TOO_BIG;
293 } else {
294 result = SetRecvFromOutput(result, data, addr, read_buffer_, bytes_to_read_,
295 recvfrom_addr_resource_);
296 Post(BROWSER, PpapiHostMsg_UDPSocket_RecvSlotAvailable());
264 } 297 }
265 298
266 read_buffer_ = NULL; 299 read_buffer_ = NULL;
267 bytes_to_read_ = -1; 300 bytes_to_read_ = -1;
268 recvfrom_addr_ = addr; 301 recvfrom_addr_resource_ = NULL;
269 302
270 if (result == PP_OK) 303 RunCallback(recvfrom_callback_, result);
271 RunCallback(recvfrom_callback_, static_cast<int32_t>(data.size()));
272 else
273 RunCallback(recvfrom_callback_, result);
274 } 304 }
275 305
276 void UDPSocketResourceBase::OnPluginMsgSendToReply( 306 void UDPSocketResourceBase::OnPluginMsgSendToReply(
277 const ResourceMessageReplyParams& params, 307 const ResourceMessageReplyParams& params,
278 int32_t bytes_written) { 308 int32_t bytes_written) {
279 if (!TrackedCallback::IsPending(sendto_callback_)) 309 if (!TrackedCallback::IsPending(sendto_callback_))
280 return; 310 return;
281 311
282 if (params.result() == PP_OK) 312 if (params.result() == PP_OK)
283 RunCallback(sendto_callback_, bytes_written); 313 RunCallback(sendto_callback_, bytes_written);
284 else 314 else
285 RunCallback(sendto_callback_, params.result()); 315 RunCallback(sendto_callback_, params.result());
286 } 316 }
287 317
288 void UDPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback, 318 void UDPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback,
289 int32_t pp_result) { 319 int32_t pp_result) {
290 callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result, 320 callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result,
291 private_api_)); 321 private_api_));
292 } 322 }
293 323
324 int32_t UDPSocketResourceBase::SetRecvFromOutput(
325 int32_t browser_result,
326 const std::string& data,
327 const PP_NetAddress_Private& addr,
328 char* output_buffer,
329 int32_t num_bytes,
330 PP_Resource* output_addr) {
331 DCHECK_GE(num_bytes, static_cast<int32_t>(data.size()));
332
333 int32_t result = browser_result;
334 if (result == PP_OK && output_addr) {
335 thunk::EnterResourceCreationNoLock enter(pp_instance());
336 if (enter.succeeded()) {
337 *output_addr = enter.functions()->CreateNetAddressFromNetAddressPrivate(
338 pp_instance(), addr);
339 } else {
340 result = PP_ERROR_FAILED;
341 }
342 }
343
344 if (result == PP_OK && !data.empty())
345 memcpy(output_buffer, data.c_str(), data.size());
346
347 recvfrom_addr_ = addr;
348
349 return result == PP_OK ? static_cast<int32_t>(data.size()) : result;
350 }
351
294 } // namespace proxy 352 } // namespace proxy
295 } // namespace ppapi 353 } // 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