Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: chrome/browser/extensions/api/socket/tcp_socket.cc

Issue 183893041: Move sockets APIs out of src/chrome (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/socket/tcp_socket.h"
6
7 #include "chrome/browser/extensions/api/api_resource.h"
8 #include "net/base/address_list.h"
9 #include "net/base/ip_endpoint.h"
10 #include "net/base/net_errors.h"
11 #include "net/base/rand_callback.h"
12 #include "net/socket/tcp_client_socket.h"
13
14 namespace extensions {
15
16 const char kTCPSocketTypeInvalidError[] =
17 "Cannot call both connect and listen on the same socket.";
18 const char kSocketListenError[] = "Could not listen on the specified port.";
19
20 static base::LazyInstance<
21 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableTCPSocket> > >
22 g_factory = LAZY_INSTANCE_INITIALIZER;
23
24 // static
25 template <>
26 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableTCPSocket> >*
27 ApiResourceManager<ResumableTCPSocket>::GetFactoryInstance() {
28 return g_factory.Pointer();
29 }
30
31 static base::LazyInstance<BrowserContextKeyedAPIFactory<
32 ApiResourceManager<ResumableTCPServerSocket> > > g_server_factory =
33 LAZY_INSTANCE_INITIALIZER;
34
35 // static
36 template <>
37 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableTCPServerSocket> >*
38 ApiResourceManager<ResumableTCPServerSocket>::GetFactoryInstance() {
39 return g_server_factory.Pointer();
40 }
41
42 TCPSocket::TCPSocket(const std::string& owner_extension_id)
43 : Socket(owner_extension_id),
44 socket_mode_(UNKNOWN) {
45 }
46
47 TCPSocket::TCPSocket(net::TCPClientSocket* tcp_client_socket,
48 const std::string& owner_extension_id,
49 bool is_connected)
50 : Socket(owner_extension_id),
51 socket_(tcp_client_socket),
52 socket_mode_(CLIENT) {
53 this->is_connected_ = is_connected;
54 }
55
56 TCPSocket::TCPSocket(net::TCPServerSocket* tcp_server_socket,
57 const std::string& owner_extension_id)
58 : Socket(owner_extension_id),
59 server_socket_(tcp_server_socket),
60 socket_mode_(SERVER) {
61 }
62
63 // static
64 TCPSocket* TCPSocket::CreateSocketForTesting(
65 net::TCPClientSocket* tcp_client_socket,
66 const std::string& owner_extension_id,
67 bool is_connected) {
68 return new TCPSocket(tcp_client_socket, owner_extension_id, is_connected);
69 }
70
71 // static
72 TCPSocket* TCPSocket::CreateServerSocketForTesting(
73 net::TCPServerSocket* tcp_server_socket,
74 const std::string& owner_extension_id) {
75 return new TCPSocket(tcp_server_socket, owner_extension_id);
76 }
77
78 TCPSocket::~TCPSocket() {
79 Disconnect();
80 }
81
82 void TCPSocket::Connect(const std::string& address,
83 int port,
84 const CompletionCallback& callback) {
85 DCHECK(!callback.is_null());
86
87 if (socket_mode_ == SERVER || !connect_callback_.is_null()) {
88 callback.Run(net::ERR_CONNECTION_FAILED);
89 return;
90 }
91 DCHECK(!server_socket_.get());
92 socket_mode_ = CLIENT;
93 connect_callback_ = callback;
94
95 int result = net::ERR_CONNECTION_FAILED;
96 do {
97 if (is_connected_)
98 break;
99
100 net::AddressList address_list;
101 if (!StringAndPortToAddressList(address, port, &address_list)) {
102 result = net::ERR_ADDRESS_INVALID;
103 break;
104 }
105
106 socket_.reset(new net::TCPClientSocket(address_list, NULL,
107 net::NetLog::Source()));
108
109 connect_callback_ = callback;
110 result = socket_->Connect(base::Bind(
111 &TCPSocket::OnConnectComplete, base::Unretained(this)));
112 } while (false);
113
114 if (result != net::ERR_IO_PENDING)
115 OnConnectComplete(result);
116 }
117
118 void TCPSocket::Disconnect() {
119 is_connected_ = false;
120 if (socket_.get())
121 socket_->Disconnect();
122 server_socket_.reset(NULL);
123 connect_callback_.Reset();
124 read_callback_.Reset();
125 accept_callback_.Reset();
126 accept_socket_.reset(NULL);
127 }
128
129 int TCPSocket::Bind(const std::string& address, int port) {
130 return net::ERR_FAILED;
131 }
132
133 void TCPSocket::Read(int count,
134 const ReadCompletionCallback& callback) {
135 DCHECK(!callback.is_null());
136
137 if (socket_mode_ != CLIENT) {
138 callback.Run(net::ERR_FAILED, NULL);
139 return;
140 }
141
142 if (!read_callback_.is_null()) {
143 callback.Run(net::ERR_IO_PENDING, NULL);
144 return;
145 }
146
147 if (count < 0) {
148 callback.Run(net::ERR_INVALID_ARGUMENT, NULL);
149 return;
150 }
151
152 if (!socket_.get() || !IsConnected()) {
153 callback.Run(net::ERR_SOCKET_NOT_CONNECTED, NULL);
154 return;
155 }
156
157 read_callback_ = callback;
158 scoped_refptr<net::IOBuffer> io_buffer = new net::IOBuffer(count);
159 int result = socket_->Read(io_buffer.get(), count,
160 base::Bind(&TCPSocket::OnReadComplete, base::Unretained(this),
161 io_buffer));
162
163 if (result != net::ERR_IO_PENDING)
164 OnReadComplete(io_buffer, result);
165 }
166
167 void TCPSocket::RecvFrom(int count,
168 const RecvFromCompletionCallback& callback) {
169 callback.Run(net::ERR_FAILED, NULL, NULL, 0);
170 }
171
172 void TCPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer,
173 int byte_count,
174 const std::string& address,
175 int port,
176 const CompletionCallback& callback) {
177 callback.Run(net::ERR_FAILED);
178 }
179
180 bool TCPSocket::SetKeepAlive(bool enable, int delay) {
181 if (!socket_.get())
182 return false;
183 return socket_->SetKeepAlive(enable, delay);
184 }
185
186 bool TCPSocket::SetNoDelay(bool no_delay) {
187 if (!socket_.get())
188 return false;
189 return socket_->SetNoDelay(no_delay);
190 }
191
192 int TCPSocket::Listen(const std::string& address, int port, int backlog,
193 std::string* error_msg) {
194 if (socket_mode_ == CLIENT) {
195 *error_msg = kTCPSocketTypeInvalidError;
196 return net::ERR_NOT_IMPLEMENTED;
197 }
198 DCHECK(!socket_.get());
199 socket_mode_ = SERVER;
200
201 scoped_ptr<net::IPEndPoint> bind_address(new net::IPEndPoint());
202 if (!StringAndPortToIPEndPoint(address, port, bind_address.get()))
203 return net::ERR_INVALID_ARGUMENT;
204
205 if (!server_socket_.get()) {
206 server_socket_.reset(new net::TCPServerSocket(NULL,
207 net::NetLog::Source()));
208 }
209 int result = server_socket_->Listen(*bind_address, backlog);
210 if (result)
211 *error_msg = kSocketListenError;
212 return result;
213 }
214
215 void TCPSocket::Accept(const AcceptCompletionCallback &callback) {
216 if (socket_mode_ != SERVER || !server_socket_.get()) {
217 callback.Run(net::ERR_FAILED, NULL);
218 return;
219 }
220
221 // Limits to only 1 blocked accept call.
222 if (!accept_callback_.is_null()) {
223 callback.Run(net::ERR_FAILED, NULL);
224 return;
225 }
226
227 int result = server_socket_->Accept(&accept_socket_, base::Bind(
228 &TCPSocket::OnAccept, base::Unretained(this)));
229 if (result == net::ERR_IO_PENDING) {
230 accept_callback_ = callback;
231 } else if (result == net::OK) {
232 accept_callback_ = callback;
233 this->OnAccept(result);
234 } else {
235 callback.Run(result, NULL);
236 }
237 }
238
239 bool TCPSocket::IsConnected() {
240 RefreshConnectionStatus();
241 return is_connected_;
242 }
243
244 bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) {
245 if (!socket_.get())
246 return false;
247 return !socket_->GetPeerAddress(address);
248 }
249
250 bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) {
251 if (socket_.get()) {
252 return !socket_->GetLocalAddress(address);
253 } else if (server_socket_.get()) {
254 return !server_socket_->GetLocalAddress(address);
255 } else {
256 return false;
257 }
258 }
259
260 Socket::SocketType TCPSocket::GetSocketType() const {
261 return Socket::TYPE_TCP;
262 }
263
264 int TCPSocket::WriteImpl(net::IOBuffer* io_buffer,
265 int io_buffer_size,
266 const net::CompletionCallback& callback) {
267 if (socket_mode_ != CLIENT)
268 return net::ERR_FAILED;
269 else if (!socket_.get() || !IsConnected())
270 return net::ERR_SOCKET_NOT_CONNECTED;
271 else
272 return socket_->Write(io_buffer, io_buffer_size, callback);
273 }
274
275 void TCPSocket::RefreshConnectionStatus() {
276 if (!is_connected_) return;
277 if (server_socket_) return;
278 if (!socket_->IsConnected()) {
279 Disconnect();
280 }
281 }
282
283 void TCPSocket::OnConnectComplete(int result) {
284 DCHECK(!connect_callback_.is_null());
285 DCHECK(!is_connected_);
286 is_connected_ = result == net::OK;
287 connect_callback_.Run(result);
288 connect_callback_.Reset();
289 }
290
291 void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
292 int result) {
293 DCHECK(!read_callback_.is_null());
294 read_callback_.Run(result, io_buffer);
295 read_callback_.Reset();
296 }
297
298 void TCPSocket::OnAccept(int result) {
299 DCHECK(!accept_callback_.is_null());
300 if (result == net::OK && accept_socket_.get()) {
301 accept_callback_.Run(
302 result, static_cast<net::TCPClientSocket*>(accept_socket_.release()));
303 } else {
304 accept_callback_.Run(result, NULL);
305 }
306 accept_callback_.Reset();
307 }
308
309 ResumableTCPSocket::ResumableTCPSocket(const std::string& owner_extension_id)
310 : TCPSocket(owner_extension_id),
311 persistent_(false),
312 buffer_size_(0),
313 paused_(false) {
314 }
315
316 ResumableTCPSocket::ResumableTCPSocket(net::TCPClientSocket* tcp_client_socket,
317 const std::string& owner_extension_id,
318 bool is_connected)
319 : TCPSocket(tcp_client_socket, owner_extension_id, is_connected),
320 persistent_(false),
321 buffer_size_(0),
322 paused_(false) {
323 }
324
325 bool ResumableTCPSocket::IsPersistent() const {
326 return persistent();
327 }
328
329 ResumableTCPServerSocket::ResumableTCPServerSocket(
330 const std::string& owner_extension_id)
331 : TCPSocket(owner_extension_id),
332 persistent_(false),
333 paused_(false) {
334 }
335
336 bool ResumableTCPServerSocket::IsPersistent() const {
337 return persistent();
338 }
339
340 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698