Chromium Code Reviews| 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 |