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