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 // |num_bytes| value is checked on the plugin side. |
| 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 (data.empty() || |
| 152 data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) { |
| 153 return PP_ERROR_BADARGUMENT; |
| 154 } |
| 155 if (send_to_context_.get() || sendto_buffer_.get()) |
| 156 return PP_ERROR_INPROGRESS; |
| 157 send_to_context_.reset( |
| 158 new ppapi::host::ReplyMessageContext(context->MakeReplyMessageContext())); |
| 159 int num_bytes = data.size(); |
| 160 if (num_bytes > ppapi::proxy::UDPSocketPrivateResource::kMaxWriteSize) { |
| 161 // Size of |data| is checked on the plugin side. |
| 162 NOTREACHED(); |
| 163 num_bytes = ppapi::proxy::UDPSocketPrivateResource::kMaxWriteSize; |
| 164 } |
| 165 sendto_buffer_ = new net::IOBufferWithSize(num_bytes); |
| 166 memcpy(sendto_buffer_->data(), data.data(), num_bytes); |
| 167 SocketPermissionRequest params = |
| 168 pepper_socket_utils::CreateSocketPermissionRequest( |
| 169 SocketPermissionRequest::UDP_SEND_TO, addr); |
| 170 CheckSocketPermissionsAndReply(params, |
| 171 base::Bind( |
| 172 &PepperUDPSocketPrivateHost::DoSendTo, |
| 173 weak_factory_.GetWeakPtr(), |
| 174 addr)); |
| 175 return PP_OK_COMPLETIONPENDING; |
| 176 } |
| 177 |
| 178 int32_t PepperUDPSocketPrivateHost::OnMsgClose( |
| 179 const ppapi::host::HostMessageContext* context) { |
| 180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 181 Close(); |
| 182 return PP_OK; |
| 183 } |
| 184 |
| 185 void PepperUDPSocketPrivateHost::DoBind(const PP_NetAddress_Private& addr, |
| 186 bool allowed) { |
| 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 188 DCHECK(!closed()); |
| 189 |
| 190 if (!allowed) { |
| 191 SendBindError(); |
| 192 return; |
| 193 } |
| 194 |
| 195 socket_.reset(new net::UDPServerSocket(NULL, net::NetLog::Source())); |
| 196 |
| 197 net::IPAddressNumber address; |
| 198 int port; |
| 199 if (!socket_.get() || |
| 200 !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { |
| 201 SendBindError(); |
| 202 return; |
| 203 } |
| 204 |
| 205 if (allow_address_reuse_) |
| 206 socket_->AllowAddressReuse(); |
| 207 if (allow_broadcast_) |
| 208 socket_->AllowBroadcast(); |
| 209 |
| 210 int result = socket_->Listen(net::IPEndPoint(address, port)); |
| 211 |
| 212 if (result == net::OK && |
| 213 socket_->GetLocalAddress(&bound_address_) != net::OK) { |
| 214 SendBindError(); |
| 215 return; |
| 216 } |
| 217 |
| 218 OnBindCompleted(result); |
| 219 } |
| 220 |
| 221 void PepperUDPSocketPrivateHost::DoSendTo(const PP_NetAddress_Private& addr, |
| 222 bool allowed) { |
| 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 224 DCHECK(socket_.get()); |
| 225 DCHECK(sendto_buffer_.get()); |
| 226 DCHECK(!closed()); |
| 227 |
| 228 if (!allowed) { |
| 229 SendSendToError(); |
| 230 return; |
| 231 } |
| 232 |
| 233 net::IPAddressNumber address; |
| 234 int port; |
| 235 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { |
| 236 SendSendToError(); |
| 237 return; |
| 238 } |
| 239 |
| 240 int result = socket_->SendTo( |
| 241 sendto_buffer_, sendto_buffer_->size(), net::IPEndPoint(address, port), |
| 242 base::Bind(&PepperUDPSocketPrivateHost::OnSendToCompleted, |
| 243 weak_factory_.GetWeakPtr())); |
| 244 |
| 245 if (result != net::ERR_IO_PENDING) |
| 246 OnSendToCompleted(result); |
| 247 } |
| 248 |
| 249 void PepperUDPSocketPrivateHost::Close() { |
| 250 if (socket_.get() && !closed_) |
| 251 socket_->Close(); |
| 252 closed_ = true; |
| 253 } |
| 254 |
| 255 void PepperUDPSocketPrivateHost::OnBindCompleted(int result) { |
| 256 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; |
| 257 if (result < 0 || |
| 258 !NetAddressPrivateImpl::IPEndPointToNetAddress(bound_address_.address(), |
| 259 bound_address_.port(), |
| 260 &addr)) { |
| 261 SendBindError(); |
| 262 } else { |
| 263 SendBindReply(true, addr); |
| 264 } |
| 265 } |
| 266 |
| 267 void PepperUDPSocketPrivateHost::OnRecvFromCompleted(int result) { |
| 268 DCHECK(recvfrom_buffer_.get()); |
| 269 |
| 270 // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private, |
| 271 // to send back. |
| 272 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; |
| 273 if (result < 0 || |
| 274 !NetAddressPrivateImpl::IPEndPointToNetAddress( |
| 275 recvfrom_address_.address(), |
| 276 recvfrom_address_.port(), |
| 277 &addr)) { |
| 278 SendRecvFromError(); |
| 279 } else { |
| 280 SendRecvFromReply(true, |
| 281 std::string(recvfrom_buffer_->data(), result), |
| 282 addr); |
| 283 } |
| 284 |
| 285 recvfrom_buffer_ = NULL; |
| 286 } |
| 287 |
| 288 void PepperUDPSocketPrivateHost::OnSendToCompleted(int result) { |
| 289 DCHECK(sendto_buffer_.get()); |
| 290 if (result < 0) |
| 291 SendSendToError(); |
| 292 else |
| 293 SendSendToReply(true, result); |
| 294 sendto_buffer_ = NULL; |
| 295 } |
| 296 |
| 297 void PepperUDPSocketPrivateHost::SendBindReply( |
| 298 bool succeeded, |
| 299 const PP_NetAddress_Private& addr) { |
| 300 DCHECK(bind_context_.get()); |
| 301 |
| 302 scoped_ptr<ppapi::host::ReplyMessageContext> context(bind_context_.release()); |
| 303 host()->SendReply(*context, |
| 304 PpapiPluginMsg_UDPSocketPrivate_BindReply(succeeded, addr)); |
| 305 } |
| 306 |
| 307 void PepperUDPSocketPrivateHost::SendRecvFromReply( |
| 308 bool succeeded, |
| 309 const std::string& data, |
| 310 const PP_NetAddress_Private& addr) { |
| 311 DCHECK(recv_from_context_.get()); |
| 312 |
| 313 scoped_ptr<ppapi::host::ReplyMessageContext> context( |
| 314 recv_from_context_.release()); |
| 315 host()->SendReply(*context, |
| 316 PpapiPluginMsg_UDPSocketPrivate_RecvFromReply(succeeded, |
| 317 data, |
| 318 addr)); |
| 319 } |
| 320 |
| 321 void PepperUDPSocketPrivateHost::SendSendToReply(bool succeeded, |
| 322 int32_t bytes_written) { |
| 323 DCHECK(send_to_context_.get()); |
| 324 |
| 325 scoped_ptr<ppapi::host::ReplyMessageContext> context( |
| 326 send_to_context_.release()); |
| 327 host()->SendReply(*context, |
| 328 PpapiPluginMsg_UDPSocketPrivate_SendToReply(succeeded, |
| 329 bytes_written)); |
| 330 } |
| 331 |
| 332 void PepperUDPSocketPrivateHost::CheckSocketPermissionsAndReply( |
| 333 const SocketPermissionRequest& params, |
| 334 const RequestCallback& callback) { |
| 335 pepper_socket_utils::PostOnUIThreadWithRenderViewHostAndReply( |
| 336 host_, FROM_HERE, pp_instance(), |
| 337 base::Bind(&pepper_socket_utils::CanUseSocketAPIs, |
| 338 host_->plugin_process_type(), params), |
| 339 callback); |
| 340 } |
| 341 |
| 342 void PepperUDPSocketPrivateHost::SendBindError() { |
| 343 SendBindReply(false, NetAddressPrivateImpl::kInvalidNetAddress); |
| 344 } |
| 345 |
| 346 void PepperUDPSocketPrivateHost::SendRecvFromError() { |
| 347 SendRecvFromReply(false, "", NetAddressPrivateImpl::kInvalidNetAddress); |
| 348 } |
| 349 |
| 350 void PepperUDPSocketPrivateHost::SendSendToError() { |
| 351 SendSendToReply(false, 0); |
| 352 } |
| 353 |
| 354 } // namespace content |
OLD | NEW |