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
29using ppapi::NetAddressPrivateImpl;
30using ppapi::host::NetErrorToPepperError;
31
32namespace {
33
34size_t g_num_instances = 0;
35
36}  // namespace
37
38namespace content {
39
40PepperTCPServerSocketMessageFilter::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
62PepperTCPServerSocketMessageFilter::~PepperTCPServerSocketMessageFilter() {
63  --g_num_instances;
64}
65
66// static
67size_t PepperTCPServerSocketMessageFilter::GetNumInstances() {
68  return g_num_instances;
69}
70
71scoped_refptr<base::TaskRunner>
72PepperTCPServerSocketMessageFilter::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
84int32_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
98int32_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
127int32_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
149int32_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
159void 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
196void 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
233void 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
290void 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
300void PepperTCPServerSocketMessageFilter::SendListenError(
301    const ppapi::host::ReplyMessageContext& context,
302    int32_t pp_result) {
303  SendListenReply(
304      context, pp_result, NetAddressPrivateImpl::kInvalidNetAddress);
305}
306
307void 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
320void 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