1 // Copyright 2013 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_tcp_server_socket_message_filter.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/logging.h" 10 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" 11 #include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.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/socket_permission_request.h" 15 #include "net/base/ip_endpoint.h" 16 #include "net/base/net_errors.h" 17 #include "net/base/net_util.h" 18 #include "ppapi/c/pp_errors.h" 19 #include "ppapi/c/private/ppb_net_address_private.h" 20 #include "ppapi/host/dispatch_host_message.h" 21 #include "ppapi/host/error_conversion.h" 22 #include "ppapi/host/ppapi_host.h" 23 #include "ppapi/host/resource_host.h" 24 #include "ppapi/proxy/ppapi_messages.h" 25 #include "ppapi/shared_impl/api_id.h" 26 #include "ppapi/shared_impl/ppb_tcp_socket_shared.h" 27 #include "ppapi/shared_impl/private/net_address_private_impl.h" 28 29 using ppapi::NetAddressPrivateImpl; 30 using ppapi::host::NetErrorToPepperError; 31 32 namespace { 33 34 size_t g_num_instances = 0; 35 36 } // namespace 37 38 namespace content { 39 40 PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter( 41 ContentBrowserPepperHostFactory* factory, 42 BrowserPpapiHostImpl* host, 43 PP_Instance instance, 44 bool private_api) 45 : ppapi_host_(host->GetPpapiHost()), 46 factory_(factory), 47 instance_(instance), 48 state_(STATE_BEFORE_LISTENING), 49 external_plugin_(host->external_plugin()), 50 private_api_(private_api), 51 render_process_id_(0), 52 render_view_id_(0) { 53 ++g_num_instances; 54 DCHECK(factory_); 55 DCHECK(ppapi_host_); 56 if (!host->GetRenderViewIDsForInstance(instance, 57 &render_process_id_, 58 &render_view_id_)) { 59 NOTREACHED(); 60 } 61 } 62 63 PepperTCPServerSocketMessageFilter::~PepperTCPServerSocketMessageFilter() { 64 --g_num_instances; 65 } 66 67 // static 68 size_t PepperTCPServerSocketMessageFilter::GetNumInstances() { 69 return g_num_instances; 70 } 71 72 scoped_refptr<base::TaskRunner> 73 PepperTCPServerSocketMessageFilter::OverrideTaskRunnerForMessage( 74 const IPC::Message& message) { 75 switch (message.type()) { 76 case PpapiHostMsg_TCPServerSocket_Listen::ID: 77 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 78 case PpapiHostMsg_TCPServerSocket_Accept::ID: 79 case PpapiHostMsg_TCPServerSocket_StopListening::ID: 80 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); 81 } 82 return NULL; 83 } 84 85 int32_t PepperTCPServerSocketMessageFilter::OnResourceMessageReceived( 86 const IPC::Message& msg, 87 ppapi::host::HostMessageContext* context) { 88 IPC_BEGIN_MESSAGE_MAP(PepperTCPServerSocketMessageFilter, msg) 89 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 90 PpapiHostMsg_TCPServerSocket_Listen, OnMsgListen) 91 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( 92 PpapiHostMsg_TCPServerSocket_Accept, OnMsgAccept) 93 PPAPI_DISPATCH_HOST_RESOURCE_CALL_0( 94 PpapiHostMsg_TCPServerSocket_StopListening, OnMsgStopListening) 95 IPC_END_MESSAGE_MAP() 96 return PP_ERROR_FAILED; 97 } 98 99 int32_t PepperTCPServerSocketMessageFilter::OnMsgListen( 100 const ppapi::host::HostMessageContext* context, 101 const PP_NetAddress_Private& addr, 102 int32_t backlog) { 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 104 DCHECK(context); 105 106 SocketPermissionRequest request = 107 pepper_socket_utils::CreateSocketPermissionRequest( 108 content::SocketPermissionRequest::TCP_LISTEN, addr); 109 if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, 110 private_api_, 111 &request, 112 render_process_id_, 113 render_view_id_)) { 114 return PP_ERROR_NOACCESS; 115 } 116 117 BrowserThread::PostTask( 118 BrowserThread::IO, FROM_HERE, 119 base::Bind(&PepperTCPServerSocketMessageFilter::DoListen, this, 120 context->MakeReplyMessageContext(), addr, backlog)); 121 return PP_OK_COMPLETIONPENDING; 122 } 123 124 int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept( 125 const ppapi::host::HostMessageContext* context) { 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 127 DCHECK(context); 128 129 if (state_ != STATE_LISTENING) 130 return PP_ERROR_FAILED; 131 132 state_ = STATE_ACCEPT_IN_PROGRESS; 133 ppapi::host::ReplyMessageContext reply_context( 134 context->MakeReplyMessageContext()); 135 int net_result = socket_->Accept( 136 &accepted_socket_, 137 &accepted_address_, 138 base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted, 139 base::Unretained(this), reply_context)); 140 if (net_result != net::ERR_IO_PENDING) 141 OnAcceptCompleted(reply_context, net_result); 142 return PP_OK_COMPLETIONPENDING; 143 } 144 145 int32_t PepperTCPServerSocketMessageFilter::OnMsgStopListening( 146 const ppapi::host::HostMessageContext* context) { 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 148 DCHECK(context); 149 150 state_ = STATE_CLOSED; 151 socket_.reset(); 152 return PP_OK; 153 } 154 155 void PepperTCPServerSocketMessageFilter::DoListen( 156 const ppapi::host::ReplyMessageContext& context, 157 const PP_NetAddress_Private& addr, 158 int32_t backlog) { 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 160 161 net::IPAddressNumber address; 162 int port; 163 if (state_ != STATE_BEFORE_LISTENING || 164 !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { 165 SendListenError(context, PP_ERROR_FAILED); 166 state_ = STATE_CLOSED; 167 return; 168 } 169 170 state_ = STATE_LISTEN_IN_PROGRESS; 171 172 socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source())); 173 int net_result = net::OK; 174 do { 175 net::IPEndPoint ip_end_point(address, port); 176 net_result = socket_->Open(ip_end_point.GetFamily()); 177 if (net_result != net::OK) 178 break; 179 net_result = socket_->SetDefaultOptionsForServer(); 180 if (net_result != net::OK) 181 break; 182 net_result = socket_->Bind(ip_end_point); 183 if (net_result != net::OK) 184 break; 185 net_result = socket_->Listen(backlog); 186 } while (false); 187 188 if (net_result != net::ERR_IO_PENDING) 189 OnListenCompleted(context, net_result); 190 } 191 192 void PepperTCPServerSocketMessageFilter::OnListenCompleted( 193 const ppapi::host::ReplyMessageContext& context, 194 int net_result) { 195 if (state_ != STATE_LISTEN_IN_PROGRESS) { 196 SendListenError(context, PP_ERROR_FAILED); 197 state_ = STATE_CLOSED; 198 return; 199 } 200 if (net_result != net::OK) { 201 SendListenError(context, NetErrorToPepperError(net_result)); 202 state_ = STATE_BEFORE_LISTENING; 203 return; 204 } 205 206 DCHECK(socket_.get()); 207 208 net::IPEndPoint end_point; 209 PP_NetAddress_Private addr; 210 211 int32_t pp_result = 212 NetErrorToPepperError(socket_->GetLocalAddress(&end_point)); 213 if (pp_result != PP_OK) { 214 SendListenError(context, pp_result); 215 state_ = STATE_BEFORE_LISTENING; 216 return; 217 } 218 if (!NetAddressPrivateImpl::IPEndPointToNetAddress(end_point.address(), 219 end_point.port(), 220 &addr)) { 221 SendListenError(context, PP_ERROR_FAILED); 222 state_ = STATE_BEFORE_LISTENING; 223 return; 224 } 225 226 SendListenReply(context, PP_OK, addr); 227 state_ = STATE_LISTENING; 228 } 229 230 void PepperTCPServerSocketMessageFilter::OnAcceptCompleted( 231 const ppapi::host::ReplyMessageContext& context, 232 int net_result) { 233 if (state_ != STATE_ACCEPT_IN_PROGRESS) { 234 SendAcceptError(context, PP_ERROR_FAILED); 235 state_ = STATE_CLOSED; 236 return; 237 } 238 239 state_ = STATE_LISTENING; 240 241 if (net_result != net::OK) { 242 SendAcceptError(context, NetErrorToPepperError(net_result)); 243 return; 244 } 245 246 DCHECK(accepted_socket_.get()); 247 248 net::IPEndPoint ip_end_point_local; 249 PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress; 250 PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress; 251 252 int32_t pp_result = 253 NetErrorToPepperError(accepted_socket_->GetLocalAddress( 254 &ip_end_point_local)); 255 if (pp_result != PP_OK) { 256 SendAcceptError(context, pp_result); 257 return; 258 } 259 if (!NetAddressPrivateImpl::IPEndPointToNetAddress( 260 ip_end_point_local.address(), 261 ip_end_point_local.port(), 262 &local_addr) || 263 !NetAddressPrivateImpl::IPEndPointToNetAddress( 264 accepted_address_.address(), 265 accepted_address_.port(), 266 &remote_addr)) { 267 SendAcceptError(context, PP_ERROR_FAILED); 268 return; 269 } 270 271 scoped_ptr<ppapi::host::ResourceHost> host = 272 factory_->CreateAcceptedTCPSocket( 273 instance_, ppapi::TCP_SOCKET_VERSION_PRIVATE, 274 accepted_socket_.Pass()); 275 if (!host) { 276 SendAcceptError(context, PP_ERROR_NOSPACE); 277 return; 278 } 279 int pending_resource_id = ppapi_host_->AddPendingResourceHost(host.Pass()); 280 if (pending_resource_id) { 281 SendAcceptReply(context, PP_OK, pending_resource_id, 282 local_addr, 283 remote_addr); 284 } else { 285 SendAcceptError(context, PP_ERROR_NOSPACE); 286 } 287 } 288 289 void PepperTCPServerSocketMessageFilter::SendListenReply( 290 const ppapi::host::ReplyMessageContext& context, 291 int32_t pp_result, 292 const PP_NetAddress_Private& local_addr) { 293 ppapi::host::ReplyMessageContext reply_context(context); 294 reply_context.params.set_result(pp_result); 295 SendReply(reply_context, 296 PpapiPluginMsg_TCPServerSocket_ListenReply(local_addr)); 297 } 298 299 void PepperTCPServerSocketMessageFilter::SendListenError( 300 const ppapi::host::ReplyMessageContext& context, 301 int32_t pp_result) { 302 SendListenReply(context, pp_result, 303 NetAddressPrivateImpl::kInvalidNetAddress); 304 } 305 306 void PepperTCPServerSocketMessageFilter::SendAcceptReply( 307 const ppapi::host::ReplyMessageContext& context, 308 int32_t pp_result, 309 int pending_resource_id, 310 const PP_NetAddress_Private& local_addr, 311 const PP_NetAddress_Private& remote_addr) { 312 ppapi::host::ReplyMessageContext reply_context(context); 313 reply_context.params.set_result(pp_result); 314 SendReply(reply_context, PpapiPluginMsg_TCPServerSocket_AcceptReply( 315 pending_resource_id, local_addr, remote_addr)); 316 } 317 318 void PepperTCPServerSocketMessageFilter::SendAcceptError( 319 const ppapi::host::ReplyMessageContext& context, 320 int32_t pp_result) { 321 SendAcceptReply(context, 322 pp_result, 323 0, 324 NetAddressPrivateImpl::kInvalidNetAddress, 325 NetAddressPrivateImpl::kInvalidNetAddress); 326 } 327 328 } // namespace content 329