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 | |
| 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 |