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.
5 #include "content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.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"
29 using ppapi::NetAddressPrivateImpl;
30 using ppapi::host::NetErrorToPepperError;
34 size_t g_num_instances = 0;
40 PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter(
41 ContentBrowserPepperHostFactory* factory,
42 BrowserPpapiHostImpl* host,
45 : ppapi_host_(host->GetPpapiHost()),
48 state_(STATE_BEFORE_LISTENING),
49 external_plugin_(host->external_plugin()),
50 private_api_(private_api),
51 render_process_id_(0),
56 if (!host->GetRenderViewIDsForInstance(instance,
63 PepperTCPServerSocketMessageFilter::~PepperTCPServerSocketMessageFilter() {
68 size_t PepperTCPServerSocketMessageFilter::GetNumInstances() {
69 return g_num_instances;
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);
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)
96 return PP_ERROR_FAILED;
99 int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
100 const ppapi::host::HostMessageContext* context,
101 const PP_NetAddress_Private& addr,
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
106 SocketPermissionRequest request =
107 pepper_socket_utils::CreateSocketPermissionRequest(
108 content::SocketPermissionRequest::TCP_LISTEN, addr);
109 if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
114 return PP_ERROR_NOACCESS;
117 BrowserThread::PostTask(
118 BrowserThread::IO, FROM_HERE,
119 base::Bind(&PepperTCPServerSocketMessageFilter::DoListen, this,
120 context->MakeReplyMessageContext(), addr, backlog));
121 return PP_OK_COMPLETIONPENDING;
124 int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
125 const ppapi::host::HostMessageContext* context) {
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
129 if (state_ != STATE_LISTENING)
130 return PP_ERROR_FAILED;
132 state_ = STATE_ACCEPT_IN_PROGRESS;
133 ppapi::host::ReplyMessageContext reply_context(
134 context->MakeReplyMessageContext());
135 int net_result = socket_->Accept(
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;
145 int32_t PepperTCPServerSocketMessageFilter::OnMsgStopListening(
146 const ppapi::host::HostMessageContext* context) {
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
150 state_ = STATE_CLOSED;
155 void PepperTCPServerSocketMessageFilter::DoListen(
156 const ppapi::host::ReplyMessageContext& context,
157 const PP_NetAddress_Private& addr,
159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
161 net::IPAddressNumber address;
163 if (state_ != STATE_BEFORE_LISTENING ||
164 !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
165 SendListenError(context, PP_ERROR_FAILED);
166 state_ = STATE_CLOSED;
170 state_ = STATE_LISTEN_IN_PROGRESS;
172 socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
173 int net_result = net::OK;
175 net::IPEndPoint ip_end_point(address, port);
176 net_result = socket_->Open(ip_end_point.GetFamily());
177 if (net_result != net::OK)
179 net_result = socket_->SetDefaultOptionsForServer();
180 if (net_result != net::OK)
182 net_result = socket_->Bind(ip_end_point);
183 if (net_result != net::OK)
185 net_result = socket_->Listen(backlog);
188 if (net_result != net::ERR_IO_PENDING)
189 OnListenCompleted(context, net_result);
192 void PepperTCPServerSocketMessageFilter::OnListenCompleted(
193 const ppapi::host::ReplyMessageContext& context,
195 if (state_ != STATE_LISTEN_IN_PROGRESS) {
196 SendListenError(context, PP_ERROR_FAILED);
197 state_ = STATE_CLOSED;
200 if (net_result != net::OK) {
201 SendListenError(context, NetErrorToPepperError(net_result));
202 state_ = STATE_BEFORE_LISTENING;
206 DCHECK(socket_.get());
208 net::IPEndPoint end_point;
209 PP_NetAddress_Private addr;
212 NetErrorToPepperError(socket_->GetLocalAddress(&end_point));
213 if (pp_result != PP_OK) {
214 SendListenError(context, pp_result);
215 state_ = STATE_BEFORE_LISTENING;
218 if (!NetAddressPrivateImpl::IPEndPointToNetAddress(end_point.address(),
221 SendListenError(context, PP_ERROR_FAILED);
222 state_ = STATE_BEFORE_LISTENING;
226 SendListenReply(context, PP_OK, addr);
227 state_ = STATE_LISTENING;
230 void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
231 const ppapi::host::ReplyMessageContext& context,
233 if (state_ != STATE_ACCEPT_IN_PROGRESS) {
234 SendAcceptError(context, PP_ERROR_FAILED);
235 state_ = STATE_CLOSED;
239 state_ = STATE_LISTENING;
241 if (net_result != net::OK) {
242 SendAcceptError(context, NetErrorToPepperError(net_result));
246 DCHECK(accepted_socket_.get());
248 net::IPEndPoint ip_end_point_local;
249 PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
250 PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
253 NetErrorToPepperError(accepted_socket_->GetLocalAddress(
254 &ip_end_point_local));
255 if (pp_result != PP_OK) {
256 SendAcceptError(context, pp_result);
259 if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
260 ip_end_point_local.address(),
261 ip_end_point_local.port(),
263 !NetAddressPrivateImpl::IPEndPointToNetAddress(
264 accepted_address_.address(),
265 accepted_address_.port(),
267 SendAcceptError(context, PP_ERROR_FAILED);
271 scoped_ptr<ppapi::host::ResourceHost> host =
272 factory_->CreateAcceptedTCPSocket(
273 instance_, ppapi::TCP_SOCKET_VERSION_PRIVATE,
274 accepted_socket_.Pass());
276 SendAcceptError(context, PP_ERROR_NOSPACE);
279 int pending_resource_id = ppapi_host_->AddPendingResourceHost(host.Pass());
280 if (pending_resource_id) {
281 SendAcceptReply(context, PP_OK, pending_resource_id,
285 SendAcceptError(context, PP_ERROR_NOSPACE);
289 void PepperTCPServerSocketMessageFilter::SendListenReply(
290 const ppapi::host::ReplyMessageContext& context,
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));
299 void PepperTCPServerSocketMessageFilter::SendListenError(
300 const ppapi::host::ReplyMessageContext& context,
302 SendListenReply(context, pp_result,
303 NetAddressPrivateImpl::kInvalidNetAddress);
306 void PepperTCPServerSocketMessageFilter::SendAcceptReply(
307 const ppapi::host::ReplyMessageContext& context,
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));
318 void PepperTCPServerSocketMessageFilter::SendAcceptError(
319 const ppapi::host::ReplyMessageContext& context,
321 SendAcceptReply(context,
324 NetAddressPrivateImpl::kInvalidNetAddress,
325 NetAddressPrivateImpl::kInvalidNetAddress);
328 } // namespace content