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

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

Issue 7745005: Initial work for UDP Pepper API (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: change bind_in_progress_ to binded_ check sendto Created 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ppapi/proxy/ppb_flash_udp_socket_proxy.h"
6
7 #include <algorithm>
8 #include <cstring>
9 #include <map>
10
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h"
14 #include "base/task.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/proxy/plugin_dispatcher.h"
17 #include "ppapi/proxy/plugin_resource_tracker.h"
18 #include "ppapi/proxy/ppapi_messages.h"
19 #include "ppapi/shared_impl/resource.h"
20 #include "ppapi/thunk/ppb_flash_udp_socket_api.h"
21 #include "ppapi/thunk/thunk.h"
22
23 using ppapi::thunk::PPB_Flash_UDPSocket_API;
24
25 namespace ppapi {
26 namespace proxy {
27
28 const int32_t kFlashUDPSocketMaxReadSize = 1024 * 1024;
29 const int32_t kFlashUDPSocketMaxWriteSize = 1024 * 1024;
30
31 class FlashUDPSocket;
32
33 namespace {
34
35 typedef std::map<uint32, FlashUDPSocket*> IDToSocketMap;
36 IDToSocketMap* g_id_to_socket = NULL;
37
38 class AbortCallbackTask : public Task {
39 public:
40 explicit AbortCallbackTask(PP_CompletionCallback callback)
41 : callback_(callback) {}
42 virtual ~AbortCallbackTask() {}
43 virtual void Run() {
44 if (callback_.func)
45 PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED);
46 }
47
48 private:
49 PP_CompletionCallback callback_;
50 };
51
52 InterfaceProxy* CreateFlashUDPSocketProxy(Dispatcher* dispatcher) {
53 return new PPB_Flash_UDPSocket_Proxy(dispatcher);
54 }
55
56 } // namespace
57
58 class FlashUDPSocket : public PPB_Flash_UDPSocket_API,
brettw 2011/09/22 20:03:30 I think this class can be in the anonymous namespa
mtilburg 2011/09/23 17:30:28 Done.
59 public Resource {
60 public:
61 FlashUDPSocket(const HostResource& resource, uint32 socket_id);
62 virtual ~FlashUDPSocket();
63
64 // ResourceObjectBase overrides.
65 virtual PPB_Flash_UDPSocket_API* AsPPB_Flash_UDPSocket_API() OVERRIDE;
66
67 // PPB_Flash_UDPSocket_API implementation.
68 virtual int32_t Bind(const PP_Flash_NetAddress* addr,
69 PP_CompletionCallback callback) OVERRIDE;
70 virtual int32_t RecvFrom(char* buffer,
71 int32_t num_bytes,
72 PP_CompletionCallback callback) OVERRIDE;
73 virtual PP_Bool GetRecvFromAddress(PP_Flash_NetAddress* addr) OVERRIDE;
74
75 virtual int32_t SendTo(const char* buffer,
76 int32_t num_bytes,
77 const PP_Flash_NetAddress* addr,
78 PP_CompletionCallback callback) OVERRIDE;
79 virtual void Close() OVERRIDE;
80
81 // Notifications from the proxy.
82 void OnBindCompleted(bool succeeded);
83 void OnRecvFromCompleted(bool succeeded,
84 const std::string& data,
85 const PP_Flash_NetAddress& addr);
86 void OnSendToCompleted(bool succeeded,
87 int32_t bytes_written);
88
89 private:
90 void PostAbortAndClearIfNecessary(PP_CompletionCallback* callback);
91
92 PluginDispatcher* GetDispatcher() const {
93 return PluginDispatcher::GetForResource(this);
94 }
95
96 uint32 socket_id_;
97
98 bool binded_;
99
100 PP_CompletionCallback bind_callback_;
101 PP_CompletionCallback recvfrom_callback_;
102 PP_CompletionCallback sendto_callback_;
103
104 char* read_buffer_;
105 int32_t bytes_to_read_;
106
107 PP_Flash_NetAddress recvfrom_addr_;
108
109 DISALLOW_COPY_AND_ASSIGN(FlashUDPSocket);
110 };
111
112 FlashUDPSocket::FlashUDPSocket(const HostResource& resource,
113 uint32 socket_id)
114 : Resource(resource),
115 socket_id_(socket_id),
116 binded_(false),
117 bind_callback_(PP_BlockUntilComplete()),
118 recvfrom_callback_(PP_BlockUntilComplete()),
119 sendto_callback_(PP_BlockUntilComplete()),
120 read_buffer_(NULL),
121 bytes_to_read_(-1) {
122 DCHECK(socket_id != 0);
123
124 recvfrom_addr_.size = 0;
125 memset(recvfrom_addr_.data, 0, sizeof(recvfrom_addr_.data));
126
127 if (!g_id_to_socket)
128 g_id_to_socket = new IDToSocketMap();
129 DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end());
130 (*g_id_to_socket)[socket_id] = this;
131 }
132
133 FlashUDPSocket::~FlashUDPSocket() {
134 Close();
135 }
136
137 PPB_Flash_UDPSocket_API* FlashUDPSocket::AsPPB_Flash_UDPSocket_API() {
138 return this;
139 }
140
141 int32_t FlashUDPSocket::Bind(const PP_Flash_NetAddress* addr,
142 PP_CompletionCallback callback) {
143 if (!addr || !callback.func)
144 return PP_ERROR_BADARGUMENT;
145 if (binded_)
146 return PP_ERROR_FAILED;
147 if (bind_callback_.func)
148 return PP_ERROR_INPROGRESS;
149
150 bind_callback_ = callback;
151
152 GetDispatcher()->SendToBrowser(
153 new PpapiHostMsg_PPBFlashUDPSocket_Bind(socket_id_, *addr));
154
155 return PP_OK_COMPLETIONPENDING;
156 }
157
158 int32_t FlashUDPSocket::RecvFrom(char* buffer,
159 int32_t num_bytes,
160 PP_CompletionCallback callback) {
161 if (!buffer || num_bytes <= 0 || !callback.func)
162 return PP_ERROR_BADARGUMENT;
163
164 if (recvfrom_callback_.func)
165 return PP_ERROR_INPROGRESS;
166
167 read_buffer_ = buffer;
168 bytes_to_read_ = std::min(num_bytes, kFlashUDPSocketMaxReadSize);
169 recvfrom_callback_ = callback;
170
171 // Send the request, the browser will call us back via RecvFromACK.
172 GetDispatcher()->SendToBrowser(
173 new PpapiHostMsg_PPBFlashUDPSocket_RecvFrom(
174 socket_id_, num_bytes));
175 return PP_OK_COMPLETIONPENDING;
176 }
177
178 PP_Bool FlashUDPSocket::GetRecvFromAddress(PP_Flash_NetAddress* addr) {
179 if (!addr)
180 return PP_FALSE;
181
182 *addr = recvfrom_addr_;
183 return PP_TRUE;
184 }
185
186 int32_t FlashUDPSocket::SendTo(const char* buffer,
187 int32_t num_bytes,
188 const PP_Flash_NetAddress* addr,
189 PP_CompletionCallback callback) {
190 if (!buffer || num_bytes <= 0 || !addr || !callback.func)
191 return PP_ERROR_BADARGUMENT;
192 if (sendto_callback_.func)
193 return PP_ERROR_INPROGRESS;
194
195 if (num_bytes > kFlashUDPSocketMaxWriteSize)
196 num_bytes = kFlashUDPSocketMaxWriteSize;
197
198 sendto_callback_ = callback;
199
200 // Send the request, the browser will call us back via SendToACK.
201 GetDispatcher()->SendToBrowser(
202 new PpapiHostMsg_PPBFlashUDPSocket_SendTo(
203 socket_id_, std::string(buffer, num_bytes), *addr));
204
205 return PP_OK_COMPLETIONPENDING;
206 }
207
208 void FlashUDPSocket::Close() {
209 if (!binded_)
yzshen1 2011/09/22 20:07:04 It is not right to use binded_ to decide whether C
mtilburg 2011/09/23 17:30:28 I've added checks at the beginning of Bind/SendTo/
yzshen1 2011/09/23 18:06:58 No. Please note that line 212-223 is teardown code
mtilburg 2011/09/23 18:36:55 Okay, I added closed_, and check it before I execu
210 return;
211
212 binded_ = false;
213
214 // After removed from the mapping, this object won't receive any notfications
215 // from the proxy.
216 DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end());
217 g_id_to_socket->erase(socket_id_);
218
219 GetDispatcher()->SendToBrowser(
220 new PpapiHostMsg_PPBFlashUDPSocket_Close(socket_id_));
221 socket_id_ = 0;
222
223 PostAbortAndClearIfNecessary(&bind_callback_);
224 PostAbortAndClearIfNecessary(&recvfrom_callback_);
225 PostAbortAndClearIfNecessary(&sendto_callback_);
226 }
227
228 void FlashUDPSocket::OnBindCompleted(bool succeeded) {
229 if (!bind_callback_.func) {
230 NOTREACHED();
231 return;
232 }
233
234 if (succeeded)
235 binded_ = true;
236
237 PP_RunAndClearCompletionCallback(&bind_callback_,
238 succeeded ? PP_OK : PP_ERROR_FAILED);
239 }
240
241 void FlashUDPSocket::OnRecvFromCompleted(bool succeeded,
242 const std::string& data,
243 const PP_Flash_NetAddress& addr) {
244 if (!recvfrom_callback_.func || !read_buffer_) {
245 NOTREACHED();
246 return;
247 }
248
249 if (succeeded) {
250 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
251 if (!data.empty())
252 memcpy(read_buffer_, data.c_str(), data.size());
253 }
254 read_buffer_ = NULL;
255 bytes_to_read_ = -1;
256 recvfrom_addr_ = addr;
257
258 PP_RunAndClearCompletionCallback(
259 &recvfrom_callback_,
260 succeeded ? static_cast<int32_t>(data.size()) :
261 static_cast<int32_t>(PP_ERROR_FAILED));
262 }
263
264 void FlashUDPSocket::OnSendToCompleted(bool succeeded,
265 int32_t bytes_written) {
266 if (!sendto_callback_.func) {
267 NOTREACHED();
268 return;
269 }
270
271 PP_RunAndClearCompletionCallback(
272 &sendto_callback_,
273 succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED));
274 }
275
276 void FlashUDPSocket::PostAbortAndClearIfNecessary(
277 PP_CompletionCallback* callback) {
278 DCHECK(callback);
279
280 if (callback->func) {
281 MessageLoop::current()->PostTask(FROM_HERE,
282 new AbortCallbackTask(*callback));
283 *callback = PP_BlockUntilComplete();
284 }
285 }
286
287 PPB_Flash_UDPSocket_Proxy::PPB_Flash_UDPSocket_Proxy(Dispatcher* dispatcher)
288 : InterfaceProxy(dispatcher) {
289 }
290
291 PPB_Flash_UDPSocket_Proxy::~PPB_Flash_UDPSocket_Proxy() {
292 }
293
294 // static
295 const InterfaceProxy::Info* PPB_Flash_UDPSocket_Proxy::GetInfo() {
296 static const Info info = {
297 ::ppapi::thunk::GetPPB_Flash_UDPSocket_Thunk(),
298 PPB_FLASH_UDPSOCKET_INTERFACE,
299 INTERFACE_ID_PPB_FLASH_UDPSOCKET,
300 false,
301 &CreateFlashUDPSocketProxy,
302 };
303 return &info;
304 }
305
306 // static
307 PP_Resource PPB_Flash_UDPSocket_Proxy::CreateProxyResource(
308 PP_Instance instance) {
309 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
310 if (!dispatcher)
311 return 0;
312
313 uint32 socket_id = 0;
314 dispatcher->SendToBrowser(new PpapiHostMsg_PPBFlashUDPSocket_Create(
315 INTERFACE_ID_PPB_FLASH_UDPSOCKET, dispatcher->plugin_dispatcher_id(),
316 &socket_id));
317 if (socket_id == 0)
318 return 0;
319
320 return (new FlashUDPSocket(HostResource::MakeInstanceOnly(instance),
321 socket_id))->GetReference();
322 }
323
324 bool PPB_Flash_UDPSocket_Proxy::OnMessageReceived(const IPC::Message& msg) {
325 bool handled = true;
326 IPC_BEGIN_MESSAGE_MAP(PPB_Flash_UDPSocket_Proxy, msg)
327 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashUDPSocket_BindACK,
328 OnMsgBindACK)
329 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashUDPSocket_RecvFromACK,
330 OnMsgRecvFromACK)
331 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFlashUDPSocket_SendToACK,
332 OnMsgSendToACK)
333 IPC_MESSAGE_UNHANDLED(handled = false)
334 IPC_END_MESSAGE_MAP()
335 return handled;
336 }
337
338 void PPB_Flash_UDPSocket_Proxy::OnMsgBindACK(
339 uint32 /* plugin_dispatcher_id */,
340 uint32 socket_id,
341 bool succeeded) {
342 if (!g_id_to_socket) {
343 NOTREACHED();
344 return;
345 }
346 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
347 if (iter == g_id_to_socket->end())
348 return;
349 iter->second->OnBindCompleted(succeeded);
350 }
351
352 void PPB_Flash_UDPSocket_Proxy::OnMsgRecvFromACK(
353 uint32 /* plugin_dispatcher_id */,
354 uint32 socket_id,
355 bool succeeded,
356 const std::string& data,
357 const PP_Flash_NetAddress& addr) {
358 if (!g_id_to_socket) {
359 NOTREACHED();
360 return;
361 }
362 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
363 if (iter == g_id_to_socket->end())
364 return;
365 iter->second->OnRecvFromCompleted(succeeded, data, addr);
366 }
367
368 void PPB_Flash_UDPSocket_Proxy::OnMsgSendToACK(
369 uint32 /* plugin_dispatcher_id */,
370 uint32 socket_id,
371 bool succeeded,
372 int32_t bytes_written) {
373 if (!g_id_to_socket) {
374 NOTREACHED();
375 return;
376 }
377 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
378 if (iter == g_id_to_socket->end())
379 return;
380 iter->second->OnSendToCompleted(succeeded, bytes_written);
381 }
382
383 } // namespace proxy
384 } // namespace ppapi
385
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698