OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/ppb_udp_socket_private_proxy.h" | 5 #include "ppapi/proxy/ppb_udp_socket_private_proxy.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 #include <map> | 9 #include <map> |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
14 #include "base/task.h" | 14 #include "base/task.h" |
15 #include "ppapi/c/pp_errors.h" | 15 #include "ppapi/c/pp_errors.h" |
16 #include "ppapi/proxy/plugin_dispatcher.h" | 16 #include "ppapi/proxy/plugin_dispatcher.h" |
17 #include "ppapi/proxy/plugin_resource_tracker.h" | 17 #include "ppapi/proxy/plugin_resource_tracker.h" |
18 #include "ppapi/proxy/ppapi_messages.h" | 18 #include "ppapi/proxy/ppapi_messages.h" |
19 #include "ppapi/shared_impl/resource.h" | 19 #include "ppapi/shared_impl/resource.h" |
20 #include "ppapi/thunk/ppb_udp_socket_private_api.h" | 20 #include "ppapi/shared_impl/udp_socket_impl.h" |
21 #include "ppapi/thunk/thunk.h" | 21 #include "ppapi/thunk/thunk.h" |
22 | 22 |
23 using ppapi::thunk::PPB_UDPSocket_Private_API; | |
24 | |
25 namespace ppapi { | 23 namespace ppapi { |
26 namespace proxy { | 24 namespace proxy { |
27 | 25 |
28 const int32_t kUDPSocketMaxReadSize = 1024 * 1024; | |
29 const int32_t kUDPSocketMaxWriteSize = 1024 * 1024; | |
30 | |
31 namespace { | 26 namespace { |
32 | 27 |
33 class UDPSocket; | 28 typedef std::map<uint32, UDPSocketImpl*> IDToSocketMap; |
34 | |
35 typedef std::map<uint32, UDPSocket*> IDToSocketMap; | |
36 IDToSocketMap* g_id_to_socket = NULL; | 29 IDToSocketMap* g_id_to_socket = NULL; |
37 | 30 |
38 class AbortCallbackTask : public Task { | 31 class AbortCallbackTask : public Task { |
39 public: | 32 public: |
40 explicit AbortCallbackTask(PP_CompletionCallback callback) | 33 explicit AbortCallbackTask(PP_CompletionCallback callback) |
41 : callback_(callback) {} | 34 : callback_(callback) {} |
42 virtual ~AbortCallbackTask() {} | 35 virtual ~AbortCallbackTask() {} |
43 virtual void Run() { | 36 virtual void Run() { |
44 if (callback_.func) | 37 if (callback_.func) |
45 PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED); | 38 PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED); |
46 } | 39 } |
47 | 40 |
48 private: | 41 private: |
49 PP_CompletionCallback callback_; | 42 PP_CompletionCallback callback_; |
50 }; | 43 }; |
51 | 44 |
52 class UDPSocket : public PPB_UDPSocket_Private_API, | 45 class UDPSocket : public UDPSocketImpl { |
53 public Resource { | |
54 public: | 46 public: |
55 UDPSocket(const HostResource& resource, uint32 socket_id); | 47 UDPSocket(const HostResource& resource, uint32 socket_id); |
56 virtual ~UDPSocket(); | 48 virtual ~UDPSocket(); |
57 | 49 |
58 // ResourceObjectBase overrides. | 50 virtual void SendBind(const PP_NetAddress_Private& addr) OVERRIDE; |
59 virtual PPB_UDPSocket_Private_API* AsPPB_UDPSocket_Private_API() OVERRIDE; | 51 virtual void SendRecvFrom(int32_t num_bytes) OVERRIDE; |
60 | 52 virtual void SendSendTo(const std::string& data, |
61 // PPB_UDPSocket_Private_API implementation. | 53 const PP_NetAddress_Private& addr) OVERRIDE; |
62 virtual int32_t Bind(const PP_NetAddress_Private* addr, | 54 virtual void SendClose() OVERRIDE; |
63 PP_CompletionCallback callback) OVERRIDE; | 55 virtual void PostAbort(PP_CompletionCallback callback) OVERRIDE; |
64 virtual int32_t RecvFrom(char* buffer, | |
65 int32_t num_bytes, | |
66 PP_CompletionCallback callback) OVERRIDE; | |
67 virtual PP_Bool GetRecvFromAddress(PP_NetAddress_Private* addr) OVERRIDE; | |
68 | |
69 virtual int32_t SendTo(const char* buffer, | |
70 int32_t num_bytes, | |
71 const PP_NetAddress_Private* addr, | |
72 PP_CompletionCallback callback) OVERRIDE; | |
73 virtual void Close() OVERRIDE; | |
74 | |
75 // Notifications from the proxy. | |
76 void OnBindCompleted(bool succeeded); | |
77 void OnRecvFromCompleted(bool succeeded, | |
78 const std::string& data, | |
79 const PP_NetAddress_Private& addr); | |
80 void OnSendToCompleted(bool succeeded, | |
81 int32_t bytes_written); | |
82 | 56 |
83 private: | 57 private: |
84 void PostAbortAndClearIfNecessary(PP_CompletionCallback* callback); | 58 void SendToBrowser(IPC::Message* msg); |
85 | |
86 PluginDispatcher* GetDispatcher() const { | |
87 return PluginDispatcher::GetForResource(this); | |
88 } | |
89 | |
90 uint32 socket_id_; | |
91 | |
92 bool binded_; | |
93 bool closed_; | |
94 | |
95 PP_CompletionCallback bind_callback_; | |
96 PP_CompletionCallback recvfrom_callback_; | |
97 PP_CompletionCallback sendto_callback_; | |
98 | |
99 char* read_buffer_; | |
100 int32_t bytes_to_read_; | |
101 | |
102 PP_NetAddress_Private recvfrom_addr_; | |
103 | 59 |
104 DISALLOW_COPY_AND_ASSIGN(UDPSocket); | 60 DISALLOW_COPY_AND_ASSIGN(UDPSocket); |
105 }; | 61 }; |
106 | 62 |
107 UDPSocket::UDPSocket(const HostResource& resource, uint32 socket_id) | 63 UDPSocket::UDPSocket(const HostResource& resource, uint32 socket_id) |
108 : Resource(resource), | 64 : UDPSocketImpl(resource, socket_id) { |
109 socket_id_(socket_id), | |
110 binded_(false), | |
111 closed_(false), | |
112 bind_callback_(PP_BlockUntilComplete()), | |
113 recvfrom_callback_(PP_BlockUntilComplete()), | |
114 sendto_callback_(PP_BlockUntilComplete()), | |
115 read_buffer_(NULL), | |
116 bytes_to_read_(-1) { | |
117 DCHECK(socket_id != 0); | |
118 | |
119 recvfrom_addr_.size = 0; | |
120 memset(recvfrom_addr_.data, 0, sizeof(recvfrom_addr_.data)); | |
121 | |
122 if (!g_id_to_socket) | 65 if (!g_id_to_socket) |
123 g_id_to_socket = new IDToSocketMap(); | 66 g_id_to_socket = new IDToSocketMap(); |
124 DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end()); | 67 DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end()); |
125 (*g_id_to_socket)[socket_id] = this; | 68 (*g_id_to_socket)[socket_id] = this; |
126 } | 69 } |
127 | 70 |
128 UDPSocket::~UDPSocket() { | 71 UDPSocket::~UDPSocket() { |
129 Close(); | 72 DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end()); |
73 g_id_to_socket->erase(socket_id_); | |
130 } | 74 } |
131 | 75 |
132 PPB_UDPSocket_Private_API* UDPSocket::AsPPB_UDPSocket_Private_API() { | 76 void UDPSocket::SendToBrowser(IPC::Message* msg) { |
133 return this; | 77 PluginDispatcher::GetForResource(this)->SendToBrowser(msg); |
134 } | 78 } |
135 | 79 |
136 int32_t UDPSocket::Bind(const PP_NetAddress_Private* addr, | 80 void UDPSocket::SendBind(const PP_NetAddress_Private& addr) { |
137 PP_CompletionCallback callback) { | 81 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Bind(socket_id_, addr)); |
138 if (!addr || !callback.func) | |
139 return PP_ERROR_BADARGUMENT; | |
140 if (binded_ || closed_) | |
141 return PP_ERROR_FAILED; | |
142 if (bind_callback_.func) | |
143 return PP_ERROR_INPROGRESS; | |
144 | |
145 bind_callback_ = callback; | |
146 | |
147 GetDispatcher()->SendToBrowser( | |
148 new PpapiHostMsg_PPBUDPSocket_Bind(socket_id_, *addr)); | |
149 | |
150 return PP_OK_COMPLETIONPENDING; | |
151 } | 82 } |
152 | 83 |
153 int32_t UDPSocket::RecvFrom(char* buffer, | 84 void UDPSocket::SendRecvFrom(int32_t num_bytes) { |
154 int32_t num_bytes, | 85 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_RecvFrom(socket_id_, num_bytes)); |
155 PP_CompletionCallback callback) { | |
156 if (!buffer || num_bytes <= 0 || !callback.func) | |
157 return PP_ERROR_BADARGUMENT; | |
158 if (!binded_) | |
159 return PP_ERROR_FAILED; | |
160 if (recvfrom_callback_.func) | |
161 return PP_ERROR_INPROGRESS; | |
162 | |
163 read_buffer_ = buffer; | |
164 bytes_to_read_ = std::min(num_bytes, kUDPSocketMaxReadSize); | |
165 recvfrom_callback_ = callback; | |
166 | |
167 // Send the request, the browser will call us back via RecvFromACK. | |
168 GetDispatcher()->SendToBrowser( | |
169 new PpapiHostMsg_PPBUDPSocket_RecvFrom( | |
170 socket_id_, num_bytes)); | |
171 return PP_OK_COMPLETIONPENDING; | |
172 } | 86 } |
173 | 87 |
174 PP_Bool UDPSocket::GetRecvFromAddress(PP_NetAddress_Private* addr) { | 88 void UDPSocket::SendSendTo(const std::string& data, |
175 if (!addr) | 89 const PP_NetAddress_Private& addr) { |
176 return PP_FALSE; | 90 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_SendTo(socket_id_, data, addr)); |
177 | |
178 *addr = recvfrom_addr_; | |
179 return PP_TRUE; | |
180 } | 91 } |
181 | 92 |
182 int32_t UDPSocket::SendTo(const char* buffer, | 93 void UDPSocket::SendClose() { |
183 int32_t num_bytes, | 94 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Close(socket_id_)); |
184 const PP_NetAddress_Private* addr, | |
185 PP_CompletionCallback callback) { | |
186 if (!buffer || num_bytes <= 0 || !addr || !callback.func) | |
187 return PP_ERROR_BADARGUMENT; | |
188 if (!binded_) | |
189 return PP_ERROR_FAILED; | |
190 if (sendto_callback_.func) | |
191 return PP_ERROR_INPROGRESS; | |
192 | |
193 if (num_bytes > kUDPSocketMaxWriteSize) | |
194 num_bytes = kUDPSocketMaxWriteSize; | |
195 | |
196 sendto_callback_ = callback; | |
197 | |
198 // Send the request, the browser will call us back via SendToACK. | |
199 GetDispatcher()->SendToBrowser( | |
200 new PpapiHostMsg_PPBUDPSocket_SendTo( | |
201 socket_id_, std::string(buffer, num_bytes), *addr)); | |
202 | |
203 return PP_OK_COMPLETIONPENDING; | |
204 } | 95 } |
205 | 96 |
206 void UDPSocket::Close() { | 97 void UDPSocket::PostAbort(PP_CompletionCallback callback) { |
207 if(closed_) | 98 MessageLoop::current()->PostTask(FROM_HERE, new AbortCallbackTask(callback)); |
208 return; | |
209 | |
210 binded_ = false; | |
211 closed_ = true; | |
212 | |
213 // After removed from the mapping, this object won't receive any notfications | |
214 // from the proxy. | |
215 DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end()); | |
216 g_id_to_socket->erase(socket_id_); | |
217 | |
218 GetDispatcher()->SendToBrowser( | |
219 new PpapiHostMsg_PPBUDPSocket_Close(socket_id_)); | |
220 socket_id_ = 0; | |
221 | |
222 PostAbortAndClearIfNecessary(&bind_callback_); | |
223 PostAbortAndClearIfNecessary(&recvfrom_callback_); | |
224 PostAbortAndClearIfNecessary(&sendto_callback_); | |
225 } | 99 } |
226 | 100 |
227 void UDPSocket::OnBindCompleted(bool succeeded) { | 101 } // namespace |
228 if (!bind_callback_.func) { | |
229 NOTREACHED(); | |
230 return; | |
231 } | |
232 | 102 |
233 if (succeeded) | 103 //------------------------------------------------------------------------------ |
234 binded_ = true; | |
235 | |
236 PP_RunAndClearCompletionCallback(&bind_callback_, | |
237 succeeded ? PP_OK : PP_ERROR_FAILED); | |
238 } | |
239 | |
240 void UDPSocket::OnRecvFromCompleted(bool succeeded, | |
241 const std::string& data, | |
242 const PP_NetAddress_Private& addr) { | |
243 if (!recvfrom_callback_.func || !read_buffer_) { | |
244 NOTREACHED(); | |
245 return; | |
246 } | |
247 | |
248 if (succeeded) { | |
249 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); | |
250 if (!data.empty()) | |
251 memcpy(read_buffer_, data.c_str(), data.size()); | |
252 } | |
253 read_buffer_ = NULL; | |
254 bytes_to_read_ = -1; | |
255 recvfrom_addr_ = addr; | |
256 | |
257 PP_RunAndClearCompletionCallback( | |
258 &recvfrom_callback_, | |
259 succeeded ? static_cast<int32_t>(data.size()) : | |
260 static_cast<int32_t>(PP_ERROR_FAILED)); | |
261 } | |
262 | |
263 void UDPSocket::OnSendToCompleted(bool succeeded, int32_t bytes_written) { | |
264 if (!sendto_callback_.func) { | |
265 NOTREACHED(); | |
266 return; | |
267 } | |
268 | |
269 PP_RunAndClearCompletionCallback( | |
270 &sendto_callback_, | |
271 succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED)); | |
272 } | |
273 | |
274 void UDPSocket::PostAbortAndClearIfNecessary( | |
275 PP_CompletionCallback* callback) { | |
276 DCHECK(callback); | |
277 | |
278 if (callback->func) { | |
279 MessageLoop::current()->PostTask(FROM_HERE, | |
280 new AbortCallbackTask(*callback)); | |
281 *callback = PP_BlockUntilComplete(); | |
282 } | |
283 } | |
284 } // namespace | |
285 | 104 |
286 PPB_UDPSocket_Private_Proxy::PPB_UDPSocket_Private_Proxy(Dispatcher* dispatcher) | 105 PPB_UDPSocket_Private_Proxy::PPB_UDPSocket_Private_Proxy(Dispatcher* dispatcher) |
287 : InterfaceProxy(dispatcher) { | 106 : InterfaceProxy(dispatcher) { |
288 } | 107 } |
289 | 108 |
290 PPB_UDPSocket_Private_Proxy::~PPB_UDPSocket_Private_Proxy() { | 109 PPB_UDPSocket_Private_Proxy::~PPB_UDPSocket_Private_Proxy() { |
291 } | 110 } |
292 | 111 |
293 // static | 112 // static |
294 PP_Resource PPB_UDPSocket_Private_Proxy::CreateProxyResource( | 113 PP_Resource PPB_UDPSocket_Private_Proxy::CreateProxyResource( |
295 PP_Instance instance) { | 114 PP_Instance instance) { |
296 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | 115 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); |
297 if (!dispatcher) | 116 if (!dispatcher) |
298 return 0; | 117 return 0; |
299 | 118 |
300 uint32 socket_id = 0; | 119 uint32 socket_id = 0; |
301 dispatcher->SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Create( | 120 dispatcher->SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Create( |
302 API_ID_PPB_UDPSOCKET_PRIVATE, dispatcher->plugin_dispatcher_id(), | 121 API_ID_PPB_UDPSOCKET_PRIVATE, dispatcher->plugin_dispatcher_id(), |
303 &socket_id)); | 122 &socket_id)); |
304 if (socket_id == 0) | 123 if (socket_id == 0) |
305 return 0; | 124 return 0; |
306 | |
307 return (new UDPSocket(HostResource::MakeInstanceOnly(instance), | 125 return (new UDPSocket(HostResource::MakeInstanceOnly(instance), |
Dmitry Polukhin
2011/11/24 13:05:45
Please return empty line back to minimize changes.
ygorshenin
2011/11/24 13:40:34
Done.
| |
308 socket_id))->GetReference(); | 126 socket_id))->GetReference(); |
309 } | 127 } |
310 | 128 |
311 bool PPB_UDPSocket_Private_Proxy::OnMessageReceived(const IPC::Message& msg) { | 129 bool PPB_UDPSocket_Private_Proxy::OnMessageReceived(const IPC::Message& msg) { |
312 bool handled = true; | 130 bool handled = true; |
313 IPC_BEGIN_MESSAGE_MAP(PPB_UDPSocket_Private_Proxy, msg) | 131 IPC_BEGIN_MESSAGE_MAP(PPB_UDPSocket_Private_Proxy, msg) |
314 IPC_MESSAGE_HANDLER(PpapiMsg_PPBUDPSocket_BindACK, | 132 IPC_MESSAGE_HANDLER(PpapiMsg_PPBUDPSocket_BindACK, |
315 OnMsgBindACK) | 133 OnMsgBindACK) |
316 IPC_MESSAGE_HANDLER(PpapiMsg_PPBUDPSocket_RecvFromACK, | 134 IPC_MESSAGE_HANDLER(PpapiMsg_PPBUDPSocket_RecvFromACK, |
317 OnMsgRecvFromACK) | 135 OnMsgRecvFromACK) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 return; | 180 return; |
363 } | 181 } |
364 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id); | 182 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id); |
365 if (iter == g_id_to_socket->end()) | 183 if (iter == g_id_to_socket->end()) |
366 return; | 184 return; |
367 iter->second->OnSendToCompleted(succeeded, bytes_written); | 185 iter->second->OnSendToCompleted(succeeded, bytes_written); |
368 } | 186 } |
369 | 187 |
370 } // namespace proxy | 188 } // namespace proxy |
371 } // namespace ppapi | 189 } // namespace ppapi |
OLD | NEW |