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