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/cpp/tcp_socket.h"
6
7#include "ppapi/c/pp_errors.h"
8#include "ppapi/cpp/completion_callback.h"
9#include "ppapi/cpp/instance_handle.h"
10#include "ppapi/cpp/module_impl.h"
11
12namespace pp {
13
14namespace {
15
16template <> const char* interface_name<PPB_TCPSocket_1_0>() {
17  return PPB_TCPSOCKET_INTERFACE_1_0;
18}
19
20template <> const char* interface_name<PPB_TCPSocket_1_1>() {
21  return PPB_TCPSOCKET_INTERFACE_1_1;
22}
23
24}  // namespace
25
26TCPSocket::TCPSocket() {
27}
28
29TCPSocket::TCPSocket(const InstanceHandle& instance) {
30  if (has_interface<PPB_TCPSocket_1_1>()) {
31    PassRefFromConstructor(get_interface<PPB_TCPSocket_1_1>()->Create(
32        instance.pp_instance()));
33  } else if (has_interface<PPB_TCPSocket_1_0>()) {
34    PassRefFromConstructor(get_interface<PPB_TCPSocket_1_0>()->Create(
35        instance.pp_instance()));
36  }
37}
38
39TCPSocket::TCPSocket(PassRef, PP_Resource resource)
40    : Resource(PASS_REF, resource) {
41}
42
43TCPSocket::TCPSocket(const TCPSocket& other) : Resource(other) {
44}
45
46TCPSocket::~TCPSocket() {
47}
48
49TCPSocket& TCPSocket::operator=(const TCPSocket& other) {
50  Resource::operator=(other);
51  return *this;
52}
53
54// static
55bool TCPSocket::IsAvailable() {
56  return has_interface<PPB_TCPSocket_1_1>() ||
57         has_interface<PPB_TCPSocket_1_0>();
58}
59
60int32_t TCPSocket::Bind(const NetAddress& addr,
61                        const CompletionCallback& callback) {
62  if (has_interface<PPB_TCPSocket_1_1>()) {
63    return get_interface<PPB_TCPSocket_1_1>()->Bind(
64        pp_resource(), addr.pp_resource(), callback.pp_completion_callback());
65  }
66  return callback.MayForce(PP_ERROR_NOINTERFACE);
67}
68
69int32_t TCPSocket::Connect(const NetAddress& addr,
70                           const CompletionCallback& callback) {
71  if (has_interface<PPB_TCPSocket_1_1>()) {
72    return get_interface<PPB_TCPSocket_1_1>()->Connect(
73        pp_resource(), addr.pp_resource(), callback.pp_completion_callback());
74  }
75  if (has_interface<PPB_TCPSocket_1_0>()) {
76    return get_interface<PPB_TCPSocket_1_0>()->Connect(
77        pp_resource(), addr.pp_resource(), callback.pp_completion_callback());
78  }
79  return callback.MayForce(PP_ERROR_NOINTERFACE);
80}
81
82NetAddress TCPSocket::GetLocalAddress() const {
83  if (has_interface<PPB_TCPSocket_1_1>()) {
84    return NetAddress(
85        PASS_REF,
86        get_interface<PPB_TCPSocket_1_1>()->GetLocalAddress(pp_resource()));
87  }
88  if (has_interface<PPB_TCPSocket_1_0>()) {
89    return NetAddress(
90        PASS_REF,
91        get_interface<PPB_TCPSocket_1_0>()->GetLocalAddress(pp_resource()));
92  }
93  return NetAddress();
94}
95
96NetAddress TCPSocket::GetRemoteAddress() const {
97  if (has_interface<PPB_TCPSocket_1_1>()) {
98    return NetAddress(
99        PASS_REF,
100        get_interface<PPB_TCPSocket_1_1>()->GetRemoteAddress(pp_resource()));
101  }
102  if (has_interface<PPB_TCPSocket_1_0>()) {
103    return NetAddress(
104        PASS_REF,
105        get_interface<PPB_TCPSocket_1_0>()->GetRemoteAddress(pp_resource()));
106  }
107  return NetAddress();
108}
109
110int32_t TCPSocket::Read(char* buffer,
111                        int32_t bytes_to_read,
112                        const CompletionCallback& callback) {
113  if (has_interface<PPB_TCPSocket_1_1>()) {
114    return get_interface<PPB_TCPSocket_1_1>()->Read(
115        pp_resource(), buffer, bytes_to_read,
116        callback.pp_completion_callback());
117  }
118  if (has_interface<PPB_TCPSocket_1_0>()) {
119    return get_interface<PPB_TCPSocket_1_0>()->Read(
120        pp_resource(), buffer, bytes_to_read,
121        callback.pp_completion_callback());
122  }
123  return callback.MayForce(PP_ERROR_NOINTERFACE);
124}
125
126int32_t TCPSocket::Write(const char* buffer,
127                         int32_t bytes_to_write,
128                         const CompletionCallback& callback) {
129  if (has_interface<PPB_TCPSocket_1_1>()) {
130    return get_interface<PPB_TCPSocket_1_1>()->Write(
131        pp_resource(), buffer, bytes_to_write,
132        callback.pp_completion_callback());
133  }
134  if (has_interface<PPB_TCPSocket_1_0>()) {
135    return get_interface<PPB_TCPSocket_1_0>()->Write(
136        pp_resource(), buffer, bytes_to_write,
137        callback.pp_completion_callback());
138  }
139  return callback.MayForce(PP_ERROR_NOINTERFACE);
140}
141
142int32_t TCPSocket::Listen(int32_t backlog,
143                          const CompletionCallback& callback) {
144  if (has_interface<PPB_TCPSocket_1_1>()) {
145    return get_interface<PPB_TCPSocket_1_1>()->Listen(
146        pp_resource(), backlog, callback.pp_completion_callback());
147  }
148  return callback.MayForce(PP_ERROR_NOINTERFACE);
149}
150
151int32_t TCPSocket::Accept(
152    const CompletionCallbackWithOutput<TCPSocket>& callback) {
153  if (has_interface<PPB_TCPSocket_1_1>()) {
154    return get_interface<PPB_TCPSocket_1_1>()->Accept(
155        pp_resource(), callback.output(), callback.pp_completion_callback());
156  }
157  return callback.MayForce(PP_ERROR_NOINTERFACE);
158}
159
160void TCPSocket::Close() {
161  if (has_interface<PPB_TCPSocket_1_1>()) {
162    get_interface<PPB_TCPSocket_1_1>()->Close(pp_resource());
163  } else if (has_interface<PPB_TCPSocket_1_0>()) {
164    get_interface<PPB_TCPSocket_1_0>()->Close(pp_resource());
165  }
166}
167
168int32_t TCPSocket::SetOption(PP_TCPSocket_Option name,
169                             const Var& value,
170                             const CompletionCallback& callback) {
171  if (has_interface<PPB_TCPSocket_1_1>()) {
172    return get_interface<PPB_TCPSocket_1_1>()->SetOption(
173        pp_resource(), name, value.pp_var(), callback.pp_completion_callback());
174  }
175  if (has_interface<PPB_TCPSocket_1_0>()) {
176    return get_interface<PPB_TCPSocket_1_0>()->SetOption(
177        pp_resource(), name, value.pp_var(), callback.pp_completion_callback());
178  }
179  return callback.MayForce(PP_ERROR_NOINTERFACE);
180}
181
182}  // namespace pp
183