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 "ppapi/proxy/tcp_server_socket_private_resource.h"
6
7#include "ppapi/proxy/ppapi_messages.h"
8#include "ppapi/proxy/tcp_socket_private_resource.h"
9
10namespace ppapi {
11namespace proxy {
12
13TCPServerSocketPrivateResource::TCPServerSocketPrivateResource(
14    Connection connection,
15    PP_Instance instance)
16    : PluginResource(connection, instance),
17      state_(STATE_BEFORE_LISTENING),
18      local_addr_() {
19  SendCreate(BROWSER, PpapiHostMsg_TCPServerSocket_CreatePrivate());
20}
21
22TCPServerSocketPrivateResource::~TCPServerSocketPrivateResource() {
23}
24
25thunk::PPB_TCPServerSocket_Private_API*
26TCPServerSocketPrivateResource::AsPPB_TCPServerSocket_Private_API() {
27  return this;
28}
29
30int32_t TCPServerSocketPrivateResource::Listen(
31    const PP_NetAddress_Private* addr,
32    int32_t backlog,
33    scoped_refptr<TrackedCallback> callback) {
34  if (!addr)
35    return PP_ERROR_BADARGUMENT;
36  if (state_ != STATE_BEFORE_LISTENING)
37    return PP_ERROR_FAILED;
38  if (TrackedCallback::IsPending(listen_callback_))
39    return PP_ERROR_INPROGRESS;
40
41  listen_callback_ = callback;
42
43  // Send the request, the browser will call us back via ListenACK
44  Call<PpapiPluginMsg_TCPServerSocket_ListenReply>(
45      BROWSER,
46      PpapiHostMsg_TCPServerSocket_Listen(*addr, backlog),
47      base::Bind(&TCPServerSocketPrivateResource::OnPluginMsgListenReply,
48                 base::Unretained(this)));
49  return PP_OK_COMPLETIONPENDING;
50}
51
52int32_t TCPServerSocketPrivateResource::Accept(
53    PP_Resource* tcp_socket,
54    scoped_refptr<TrackedCallback> callback) {
55  if (!tcp_socket)
56    return PP_ERROR_BADARGUMENT;
57  if (state_ != STATE_LISTENING)
58    return PP_ERROR_FAILED;
59  if (TrackedCallback::IsPending(accept_callback_))
60    return PP_ERROR_INPROGRESS;
61
62  accept_callback_ = callback;
63
64  Call<PpapiPluginMsg_TCPServerSocket_AcceptReply>(
65      BROWSER,
66      PpapiHostMsg_TCPServerSocket_Accept(),
67      base::Bind(&TCPServerSocketPrivateResource::OnPluginMsgAcceptReply,
68                 base::Unretained(this), tcp_socket));
69  return PP_OK_COMPLETIONPENDING;
70}
71
72int32_t TCPServerSocketPrivateResource::GetLocalAddress(
73    PP_NetAddress_Private* addr) {
74  if (!addr)
75    return PP_ERROR_BADARGUMENT;
76  if (state_ != STATE_LISTENING)
77    return PP_ERROR_FAILED;
78  *addr = local_addr_;
79  return PP_OK;
80}
81
82void TCPServerSocketPrivateResource::StopListening() {
83  if (state_ == STATE_CLOSED)
84    return;
85  state_ = STATE_CLOSED;
86  Post(BROWSER, PpapiHostMsg_TCPServerSocket_StopListening());
87  if (TrackedCallback::IsPending(listen_callback_))
88    listen_callback_->PostAbort();
89  if (TrackedCallback::IsPending(accept_callback_))
90    accept_callback_->PostAbort();
91}
92
93void TCPServerSocketPrivateResource::OnPluginMsgListenReply(
94    const ResourceMessageReplyParams& params,
95    const PP_NetAddress_Private& local_addr) {
96  if (state_ != STATE_BEFORE_LISTENING ||
97      !TrackedCallback::IsPending(listen_callback_)) {
98    return;
99  }
100  if (params.result() == PP_OK) {
101    local_addr_ = local_addr;
102    state_ = STATE_LISTENING;
103  }
104  listen_callback_->Run(params.result());
105}
106
107void TCPServerSocketPrivateResource::OnPluginMsgAcceptReply(
108    PP_Resource* tcp_socket,
109    const ResourceMessageReplyParams& params,
110    int pending_resource_id,
111    const PP_NetAddress_Private& local_addr,
112    const PP_NetAddress_Private& remote_addr) {
113  DCHECK(tcp_socket);
114  if (state_ != STATE_LISTENING ||
115      !TrackedCallback::IsPending(accept_callback_)) {
116    return;
117  }
118  if (params.result() == PP_OK) {
119    *tcp_socket = (new TCPSocketPrivateResource(connection(), pp_instance(),
120                                                pending_resource_id,
121                                                local_addr,
122                                                remote_addr))->GetReference();
123  }
124  accept_callback_->Run(params.result());
125}
126
127}  // namespace proxy
128}  // namespace ppapi
129