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 <string> |
yzshen1
2011/11/29 20:19:33
You have included it in .h file.
ygorshenin
2011/11/30 11:50:54
Done.
| |
8 #include <cstring> | |
9 #include <map> | 8 #include <map> |
10 | 9 |
11 #include "base/logging.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
14 #include "base/task.h" | 11 #include "base/task.h" |
15 #include "ppapi/c/pp_errors.h" | 12 #include "ppapi/c/pp_errors.h" |
16 #include "ppapi/proxy/plugin_dispatcher.h" | 13 #include "ppapi/proxy/plugin_dispatcher.h" |
17 #include "ppapi/proxy/plugin_resource_tracker.h" | 14 #include "ppapi/proxy/plugin_resource_tracker.h" |
18 #include "ppapi/proxy/ppapi_messages.h" | 15 #include "ppapi/proxy/ppapi_messages.h" |
19 #include "ppapi/shared_impl/resource.h" | 16 #include "ppapi/shared_impl/resource.h" |
20 #include "ppapi/thunk/ppb_udp_socket_private_api.h" | 17 #include "ppapi/shared_impl/udp_socket_impl.h" |
21 #include "ppapi/thunk/thunk.h" | 18 #include "ppapi/thunk/thunk.h" |
22 | 19 |
23 using ppapi::thunk::PPB_UDPSocket_Private_API; | |
24 | |
25 namespace ppapi { | 20 namespace ppapi { |
26 namespace proxy { | 21 namespace proxy { |
27 | 22 |
28 const int32_t kUDPSocketMaxReadSize = 1024 * 1024; | |
29 const int32_t kUDPSocketMaxWriteSize = 1024 * 1024; | |
30 | |
31 namespace { | 23 namespace { |
32 | 24 |
33 class UDPSocket; | 25 typedef std::map<uint32, UDPSocketImpl*> IDToSocketMap; |
34 | |
35 typedef std::map<uint32, UDPSocket*> IDToSocketMap; | |
36 IDToSocketMap* g_id_to_socket = NULL; | 26 IDToSocketMap* g_id_to_socket = NULL; |
37 | 27 |
38 class AbortCallbackTask : public Task { | 28 class AbortCallbackTask : public Task { |
39 public: | 29 public: |
40 explicit AbortCallbackTask(PP_CompletionCallback callback) | 30 explicit AbortCallbackTask(PP_CompletionCallback callback) |
41 : callback_(callback) {} | 31 : callback_(callback) {} |
42 virtual ~AbortCallbackTask() {} | 32 virtual ~AbortCallbackTask() {} |
43 virtual void Run() { | 33 virtual void Run() { |
44 if (callback_.func) | 34 if (callback_.func) |
45 PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED); | 35 PP_RunCompletionCallback(&callback_, PP_ERROR_ABORTED); |
46 } | 36 } |
47 | 37 |
48 private: | 38 private: |
49 PP_CompletionCallback callback_; | 39 PP_CompletionCallback callback_; |
50 }; | 40 }; |
51 | 41 |
52 class UDPSocket : public PPB_UDPSocket_Private_API, | 42 class UDPSocket : public UDPSocketImpl { |
53 public Resource { | |
54 public: | 43 public: |
55 UDPSocket(const HostResource& resource, uint32 socket_id); | 44 UDPSocket(const HostResource& resource, uint32 socket_id); |
56 virtual ~UDPSocket(); | 45 virtual ~UDPSocket(); |
57 | 46 |
58 // ResourceObjectBase overrides. | 47 virtual void SendBind(const PP_NetAddress_Private& addr) OVERRIDE; |
59 virtual PPB_UDPSocket_Private_API* AsPPB_UDPSocket_Private_API() OVERRIDE; | 48 virtual void SendRecvFrom(int32_t num_bytes) OVERRIDE; |
60 | 49 virtual void SendSendTo(const std::string& data, |
61 // PPB_UDPSocket_Private_API implementation. | 50 const PP_NetAddress_Private& addr) OVERRIDE; |
62 virtual int32_t Bind(const PP_NetAddress_Private* addr, | 51 virtual void SendClose() OVERRIDE; |
63 PP_CompletionCallback callback) OVERRIDE; | 52 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 | 53 |
83 private: | 54 private: |
84 void PostAbortAndClearIfNecessary(PP_CompletionCallback* callback); | 55 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 | 56 |
104 DISALLOW_COPY_AND_ASSIGN(UDPSocket); | 57 DISALLOW_COPY_AND_ASSIGN(UDPSocket); |
105 }; | 58 }; |
106 | 59 |
107 UDPSocket::UDPSocket(const HostResource& resource, uint32 socket_id) | 60 UDPSocket::UDPSocket(const HostResource& resource, uint32 socket_id) |
108 : Resource(resource), | 61 : 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) | 62 if (!g_id_to_socket) |
123 g_id_to_socket = new IDToSocketMap(); | 63 g_id_to_socket = new IDToSocketMap(); |
124 DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end()); | 64 DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end()); |
125 (*g_id_to_socket)[socket_id] = this; | 65 (*g_id_to_socket)[socket_id] = this; |
126 } | 66 } |
127 | 67 |
128 UDPSocket::~UDPSocket() { | 68 UDPSocket::~UDPSocket() { |
129 Close(); | 69 Close(); |
130 } | 70 } |
131 | 71 |
132 PPB_UDPSocket_Private_API* UDPSocket::AsPPB_UDPSocket_Private_API() { | 72 void UDPSocket::SendBind(const PP_NetAddress_Private& addr) { |
133 return this; | 73 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Bind(socket_id_, addr)); |
134 } | 74 } |
135 | 75 |
136 int32_t UDPSocket::Bind(const PP_NetAddress_Private* addr, | 76 void UDPSocket::SendRecvFrom(int32_t num_bytes) { |
137 PP_CompletionCallback callback) { | 77 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_RecvFrom(socket_id_, num_bytes)); |
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 } | 78 } |
152 | 79 |
153 int32_t UDPSocket::RecvFrom(char* buffer, | 80 void UDPSocket::SendSendTo(const std::string& data, |
154 int32_t num_bytes, | 81 const PP_NetAddress_Private& addr) { |
155 PP_CompletionCallback callback) { | 82 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_SendTo(socket_id_, data, addr)); |
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 } | 83 } |
173 | 84 |
174 PP_Bool UDPSocket::GetRecvFromAddress(PP_NetAddress_Private* addr) { | 85 void UDPSocket::SendClose() { |
175 if (!addr) | 86 // After removed from the mapping, this object won't receive any notifications |
176 return PP_FALSE; | |
177 | |
178 *addr = recvfrom_addr_; | |
179 return PP_TRUE; | |
180 } | |
181 | |
182 int32_t UDPSocket::SendTo(const char* buffer, | |
183 int32_t num_bytes, | |
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 } | |
205 | |
206 void UDPSocket::Close() { | |
207 if(closed_) | |
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. | 87 // from the proxy. |
215 DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end()); | 88 DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end()); |
216 g_id_to_socket->erase(socket_id_); | 89 g_id_to_socket->erase(socket_id_); |
217 | 90 SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Close(socket_id_)); |
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 } | 91 } |
226 | 92 |
227 void UDPSocket::OnBindCompleted(bool succeeded) { | 93 void UDPSocket::PostAbort(PP_CompletionCallback callback) { |
228 if (!bind_callback_.func) { | 94 // TODO(ygorshenin): replace AbortCallbackTask with base::Bind |
229 NOTREACHED(); | 95 MessageLoop::current()->PostTask(FROM_HERE, new AbortCallbackTask(callback)); |
230 return; | |
231 } | |
232 | |
233 if (succeeded) | |
234 binded_ = true; | |
235 | |
236 PP_RunAndClearCompletionCallback(&bind_callback_, | |
237 succeeded ? PP_OK : PP_ERROR_FAILED); | |
238 } | 96 } |
239 | 97 |
240 void UDPSocket::OnRecvFromCompleted(bool succeeded, | 98 void UDPSocket::SendToBrowser(IPC::Message* msg) { |
241 const std::string& data, | 99 PluginDispatcher::GetForResource(this)->SendToBrowser(msg); |
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 } | 100 } |
262 | 101 |
263 void UDPSocket::OnSendToCompleted(bool succeeded, int32_t bytes_written) { | 102 } // namespace |
264 if (!sendto_callback_.func) { | |
265 NOTREACHED(); | |
266 return; | |
267 } | |
268 | 103 |
269 PP_RunAndClearCompletionCallback( | 104 //------------------------------------------------------------------------------ |
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 | 105 |
286 PPB_UDPSocket_Private_Proxy::PPB_UDPSocket_Private_Proxy(Dispatcher* dispatcher) | 106 PPB_UDPSocket_Private_Proxy::PPB_UDPSocket_Private_Proxy(Dispatcher* dispatcher) |
287 : InterfaceProxy(dispatcher) { | 107 : InterfaceProxy(dispatcher) { |
288 } | 108 } |
289 | 109 |
290 PPB_UDPSocket_Private_Proxy::~PPB_UDPSocket_Private_Proxy() { | 110 PPB_UDPSocket_Private_Proxy::~PPB_UDPSocket_Private_Proxy() { |
291 } | 111 } |
292 | 112 |
293 // static | 113 // static |
294 PP_Resource PPB_UDPSocket_Private_Proxy::CreateProxyResource( | 114 PP_Resource PPB_UDPSocket_Private_Proxy::CreateProxyResource( |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 return; | 182 return; |
363 } | 183 } |
364 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id); | 184 IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id); |
365 if (iter == g_id_to_socket->end()) | 185 if (iter == g_id_to_socket->end()) |
366 return; | 186 return; |
367 iter->second->OnSendToCompleted(succeeded, bytes_written); | 187 iter->second->OnSendToCompleted(succeeded, bytes_written); |
368 } | 188 } |
369 | 189 |
370 } // namespace proxy | 190 } // namespace proxy |
371 } // namespace ppapi | 191 } // namespace ppapi |
OLD | NEW |