OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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 "content/browser/renderer_host/pepper/pepper_udp_socket_private_host.h" | |
6 | |
7 #include <cstring> | |
8 | |
9 #include "base/compiler_specific.h" | |
10 #include "base/logging.h" | |
11 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" | |
12 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h" | |
13 #include "content/public/browser/browser_thread.h" | |
14 #include "content/public/common/process_type.h" | |
15 #include "content/public/common/socket_permission_request.h" | |
16 #include "ipc/ipc_message_macros.h" | |
17 #include "net/base/io_buffer.h" | |
18 #include "net/base/net_errors.h" | |
19 #include "net/udp/udp_server_socket.h" | |
20 #include "ppapi/c/pp_errors.h" | |
21 #include "ppapi/c/private/ppb_net_address_private.h" | |
22 #include "ppapi/c/private/ppb_udp_socket_private.h" | |
23 #include "ppapi/host/dispatch_host_message.h" | |
24 #include "ppapi/host/host_message_context.h" | |
25 #include "ppapi/host/ppapi_host.h" | |
26 #include "ppapi/proxy/ppapi_messages.h" | |
27 #include "ppapi/proxy/udp_socket_private_resource.h" | |
28 #include "ppapi/shared_impl/private/net_address_private_impl.h" | |
29 | |
30 using ppapi::NetAddressPrivateImpl; | |
31 | |
32 namespace content { | |
33 | |
34 PepperUDPSocketPrivateHost::PepperUDPSocketPrivateHost( | |
35 BrowserPpapiHostImpl* host, | |
36 PP_Instance instance, | |
37 PP_Resource resource) | |
38 : ResourceHost(host->GetPpapiHost(), instance, resource), | |
39 allow_address_reuse_(false), | |
40 allow_broadcast_(false), | |
41 closed_(false), | |
42 host_(host), | |
43 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
44 DCHECK(host_); | |
45 } | |
46 | |
47 PepperUDPSocketPrivateHost::~PepperUDPSocketPrivateHost() { | |
48 Close(); | |
49 } | |
50 | |
51 int32_t PepperUDPSocketPrivateHost::OnResourceMessageReceived( | |
52 const IPC::Message& msg, | |
53 ppapi::host::HostMessageContext* context) { | |
54 IPC_BEGIN_MESSAGE_MAP(PepperUDPSocketPrivateHost, msg) | |
55 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
56 PpapiHostMsg_UDPSocketPrivate_SetBoolSocketFeature, | |
57 OnMsgSetBoolSocketFeature) | |
58 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
59 PpapiHostMsg_UDPSocketPrivate_Bind, | |
60 OnMsgBind) | |
61 PPAPI_DISPATCH_HOST_RESOURCE_CALL( | |
62 PpapiHostMsg_UDPSocketPrivate_RecvFrom, | |
63 OnMsgRecvFrom) | |
64 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocketPrivate_SendTo, | |
65 OnMsgSendTo) | |
66 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( | |
67 PpapiHostMsg_UDPSocketPrivate_Close, | |
68 OnMsgClose) | |
69 IPC_END_MESSAGE_MAP() | |
70 return PP_ERROR_FAILED; | |
71 } | |
72 | |
73 int32_t PepperUDPSocketPrivateHost::OnMsgSetBoolSocketFeature( | |
74 const ppapi::host::HostMessageContext* context, | |
75 int32_t name, | |
76 bool value) { | |
77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
78 DCHECK(!socket_.get()); | |
79 DCHECK(!closed()); | |
80 | |
81 switch(static_cast<PP_UDPSocketFeature_Private>(name)) { | |
82 case PP_UDPSOCKETFEATURE_ADDRESS_REUSE: | |
83 allow_address_reuse_ = value; | |
84 break; | |
85 case PP_UDPSOCKETFEATURE_BROADCAST: | |
86 allow_broadcast_ = value; | |
87 break; | |
88 default: | |
89 NOTREACHED(); | |
90 break; | |
91 } | |
92 return PP_OK; | |
93 } | |
94 | |
95 int32_t PepperUDPSocketPrivateHost::OnMsgBind( | |
96 const ppapi::host::HostMessageContext* context, | |
97 const PP_NetAddress_Private& addr) { | |
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
99 DCHECK(context); | |
100 | |
101 if (bind_context_.get()) | |
102 return PP_ERROR_INPROGRESS; | |
103 bind_context_.reset( | |
104 new ppapi::host::ReplyMessageContext(context->MakeReplyMessageContext())); | |
105 | |
106 SocketPermissionRequest params = | |
107 pepper_socket_utils::CreateSocketPermissionRequest( | |
108 SocketPermissionRequest::UDP_BIND, addr); | |
109 CheckSocketPermissionsAndReply(params, | |
110 base::Bind(&PepperUDPSocketPrivateHost::DoBind, | |
111 weak_factory_.GetWeakPtr(), | |
112 addr)); | |
113 return PP_OK_COMPLETIONPENDING; | |
114 } | |
115 | |
116 int32_t PepperUDPSocketPrivateHost::OnMsgRecvFrom( | |
117 const ppapi::host::HostMessageContext* context, | |
118 int32_t num_bytes) { | |
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
120 DCHECK(context); | |
121 DCHECK(socket_.get()); | |
122 DCHECK(!closed()); | |
123 | |
124 if (recv_from_context_.get()) | |
125 return PP_ERROR_INPROGRESS; | |
126 recv_from_context_.reset( | |
127 new ppapi::host::ReplyMessageContext(context->MakeReplyMessageContext())); | |
128 if (recvfrom_buffer_.get()) | |
129 return PP_ERROR_INPROGRESS; | |
130 if (num_bytes > ppapi::proxy::UDPSocketPrivateResource::kMaxReadSize) { | |
131 NOTREACHED(); | |
132 num_bytes = ppapi::proxy::UDPSocketPrivateResource::kMaxReadSize; | |
133 } | |
134 recvfrom_buffer_ = new net::IOBuffer(num_bytes); | |
135 int result = socket_->RecvFrom( | |
136 recvfrom_buffer_, num_bytes, &recvfrom_address_, | |
137 base::Bind(&PepperUDPSocketPrivateHost::OnRecvFromCompleted, | |
138 weak_factory_.GetWeakPtr())); | |
139 if (result != net::ERR_IO_PENDING) | |
140 OnRecvFromCompleted(result); | |
141 return PP_OK_COMPLETIONPENDING; | |
142 } | |
143 | |
144 int32_t PepperUDPSocketPrivateHost::OnMsgSendTo( | |
145 const ppapi::host::HostMessageContext* context, | |
146 const std::string& data, | |
147 const PP_NetAddress_Private& addr) { | |
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
149 DCHECK(context); | |
150 | |
151 if (send_to_context_.get()) | |
152 return PP_ERROR_INPROGRESS; | |
153 send_to_context_.reset( | |
154 new ppapi::host::ReplyMessageContext(context->MakeReplyMessageContext())); | |
155 SocketPermissionRequest params = | |
156 pepper_socket_utils::CreateSocketPermissionRequest( | |
157 SocketPermissionRequest::UDP_SEND_TO, addr); | |
158 CheckSocketPermissionsAndReply(params, | |
159 base::Bind( | |
160 &PepperUDPSocketPrivateHost::DoSendTo, | |
161 weak_factory_.GetWeakPtr(), | |
162 data, | |
dmichael (off chromium)
2013/01/10 05:57:16
This is going to implicitly do a copy, which you t
ygorshenin1
2013/01/10 11:36:12
Sure, thanks!
Done.
On 2013/01/10 05:57:16, dmich
| |
163 addr)); | |
164 return PP_OK_COMPLETIONPENDING; | |
165 } | |
166 | |
167 int32_t PepperUDPSocketPrivateHost::OnMsgClose( | |
168 const ppapi::host::HostMessageContext* context) { | |
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
170 Close(); | |
171 return PP_OK; | |
172 } | |
173 | |
174 void PepperUDPSocketPrivateHost::DoBind(const PP_NetAddress_Private& addr, | |
175 bool allowed) { | |
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
177 DCHECK(!closed()); | |
178 | |
179 if (!allowed) { | |
180 SendBindError(); | |
181 return; | |
182 } | |
183 | |
184 socket_.reset(new net::UDPServerSocket(NULL, net::NetLog::Source())); | |
185 | |
186 net::IPAddressNumber address; | |
187 int port; | |
188 if (!socket_.get() || | |
189 !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { | |
190 SendBindError(); | |
191 return; | |
192 } | |
193 | |
194 if (allow_address_reuse_) | |
195 socket_->AllowAddressReuse(); | |
196 if (allow_broadcast_) | |
197 socket_->AllowBroadcast(); | |
198 | |
199 int result = socket_->Listen(net::IPEndPoint(address, port)); | |
200 | |
201 if (result == net::OK && | |
202 socket_->GetLocalAddress(&bound_address_) != net::OK) { | |
203 SendBindError(); | |
204 return; | |
205 } | |
206 | |
207 OnBindCompleted(result); | |
208 } | |
209 | |
210 void PepperUDPSocketPrivateHost::DoSendTo(const std::string& data, | |
211 const PP_NetAddress_Private& addr, | |
212 bool allowed) { | |
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
214 DCHECK(socket_.get()); | |
215 DCHECK(!closed()); | |
216 | |
217 if (!allowed || sendto_buffer_.get() || data.empty()) { | |
218 SendSendToError(); | |
219 return; | |
220 } | |
221 | |
222 net::IPAddressNumber address; | |
223 int port; | |
224 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { | |
225 SendSendToError(); | |
226 return; | |
227 } | |
228 | |
229 int data_size = data.size(); | |
230 if (data_size > ppapi::proxy::UDPSocketPrivateResource::kMaxWriteSize) { | |
231 NOTREACHED(); | |
232 data_size = ppapi::proxy::UDPSocketPrivateResource::kMaxWriteSize; | |
233 } | |
234 | |
235 sendto_buffer_ = new net::IOBuffer(data_size); | |
236 memcpy(sendto_buffer_->data(), data.data(), data_size); | |
237 int result = socket_->SendTo( | |
238 sendto_buffer_, data_size, net::IPEndPoint(address, port), | |
239 base::Bind(&PepperUDPSocketPrivateHost::OnSendToCompleted, | |
240 weak_factory_.GetWeakPtr())); | |
241 | |
242 if (result != net::ERR_IO_PENDING) | |
243 OnSendToCompleted(result); | |
244 } | |
245 | |
246 void PepperUDPSocketPrivateHost::Close() { | |
247 if (socket_.get() && !closed_) | |
248 socket_->Close(); | |
249 closed_ = true; | |
250 } | |
251 | |
252 void PepperUDPSocketPrivateHost::OnBindCompleted(int result) { | |
253 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
254 if (result < 0 || | |
255 !NetAddressPrivateImpl::IPEndPointToNetAddress(bound_address_.address(), | |
256 bound_address_.port(), | |
257 &addr)) { | |
258 SendBindError(); | |
259 } else { | |
260 SendBindReply(true, addr); | |
261 } | |
262 } | |
263 | |
264 void PepperUDPSocketPrivateHost::OnRecvFromCompleted(int result) { | |
265 DCHECK(recvfrom_buffer_.get()); | |
266 | |
267 // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private, | |
268 // to send back. | |
269 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
270 if (result < 0 || | |
271 !NetAddressPrivateImpl::IPEndPointToNetAddress( | |
272 recvfrom_address_.address(), | |
273 recvfrom_address_.port(), | |
274 &addr)) { | |
275 SendRecvFromError(); | |
276 } else { | |
277 SendRecvFromReply(true, | |
278 std::string(recvfrom_buffer_->data(), result), | |
279 addr); | |
280 } | |
281 | |
282 recvfrom_buffer_ = NULL; | |
283 } | |
284 | |
285 void PepperUDPSocketPrivateHost::OnSendToCompleted(int result) { | |
286 DCHECK(sendto_buffer_.get()); | |
287 if (result < 0) | |
288 SendSendToError(); | |
289 else | |
290 SendSendToReply(true, result); | |
291 sendto_buffer_ = NULL; | |
292 } | |
293 | |
294 void PepperUDPSocketPrivateHost::SendBindReply( | |
295 bool succeeded, | |
296 const PP_NetAddress_Private& addr) { | |
297 DCHECK(bind_context_.get()); | |
298 | |
299 scoped_ptr<ppapi::host::ReplyMessageContext> context(bind_context_.release()); | |
300 host()->SendReply(*context, | |
301 PpapiPluginMsg_UDPSocketPrivate_BindReply(succeeded, addr)); | |
302 } | |
303 | |
304 void PepperUDPSocketPrivateHost::SendRecvFromReply( | |
305 bool succeeded, | |
306 const std::string& data, | |
307 const PP_NetAddress_Private& addr) { | |
308 DCHECK(recv_from_context_.get()); | |
309 | |
310 scoped_ptr<ppapi::host::ReplyMessageContext> context( | |
311 recv_from_context_.release()); | |
312 host()->SendReply(*context, | |
313 PpapiPluginMsg_UDPSocketPrivate_RecvFromReply(succeeded, | |
314 data, | |
315 addr)); | |
316 } | |
317 | |
318 void PepperUDPSocketPrivateHost::SendSendToReply(bool succeeded, | |
dmichael (off chromium)
2013/01/10 05:57:16
Why have the succeeded parameter? You only call th
ygorshenin1
2013/01/10 11:36:12
Not exactly. These methods are also called from Se
dmichael (off chromium)
2013/01/10 17:30:47
I see, thanks for explaining.
| |
319 int32_t bytes_written) { | |
320 DCHECK(send_to_context_.get()); | |
321 | |
322 scoped_ptr<ppapi::host::ReplyMessageContext> context( | |
323 send_to_context_.release()); | |
324 host()->SendReply(*context, | |
325 PpapiPluginMsg_UDPSocketPrivate_SendToReply(succeeded, | |
326 bytes_written)); | |
327 } | |
328 | |
329 void PepperUDPSocketPrivateHost::CheckSocketPermissionsAndReply( | |
330 const SocketPermissionRequest& params, | |
331 const RequestCallback& callback) { | |
332 host_->PostOnUIThreadWithRenderViewHostAndReply( | |
333 FROM_HERE, | |
334 pp_instance(), | |
335 base::Bind(&pepper_socket_utils::CanUseSocketAPIs, | |
336 host_->plugin_process_type(), params), | |
337 callback); | |
338 } | |
339 | |
340 void PepperUDPSocketPrivateHost::SendBindError() { | |
341 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
342 SendBindReply(false, addr); | |
dmichael (off chromium)
2013/01/10 05:57:16
Shouldn't you release the context in the error cas
ygorshenin1
2013/01/10 11:36:12
{send_to|recv_from|bind}_context_ are released in
| |
343 } | |
344 | |
345 void PepperUDPSocketPrivateHost::SendRecvFromError() { | |
346 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
347 SendRecvFromReply(false, "", addr); | |
348 } | |
349 | |
350 void PepperUDPSocketPrivateHost::SendSendToError() { | |
351 SendSendToReply(false, 0); | |
352 } | |
353 | |
354 } // namespace content | |
OLD | NEW |