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