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

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

Issue 10827390: Implement chrome.socket.bind/listen/accept for TCP server socket. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unrelated changes. Created 8 years, 3 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/socket/tcp_socket.h" 5 #include "chrome/browser/extensions/api/socket/tcp_socket.h"
6 6
7 #include "chrome/browser/extensions/api/api_resource.h" 7 #include "chrome/browser/extensions/api/api_resource.h"
8 #include "chrome/browser/extensions/api/api_resource_event_notifier.h" 8 #include "chrome/browser/extensions/api/api_resource_event_notifier.h"
9 #include "net/base/address_list.h" 9 #include "net/base/address_list.h"
10 #include "net/base/ip_endpoint.h" 10 #include "net/base/ip_endpoint.h"
11 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
12 #include "net/base/rand_callback.h" 12 #include "net/base/rand_callback.h"
13 #include "net/socket/tcp_client_socket.h" 13 #include "net/socket/tcp_client_socket.h"
14 14
15 namespace extensions { 15 namespace extensions {
16 16
17 const char kTCPSocketTypeInvalidError[] =
18 "Cannot call both connect and listen on the same socket.";
19 const char kSocketListenError[] = "Could not listen on the specified port.";
20
17 TCPSocket::TCPSocket(ApiResourceEventNotifier* event_notifier) 21 TCPSocket::TCPSocket(ApiResourceEventNotifier* event_notifier)
18 : Socket(event_notifier) { 22 : Socket(event_notifier),
23 is_client_socket_(false),
24 is_server_socket_(false) {
19 } 25 }
20 26
21 // For testing.
22 TCPSocket::TCPSocket(net::TCPClientSocket* tcp_client_socket, 27 TCPSocket::TCPSocket(net::TCPClientSocket* tcp_client_socket,
23 ApiResourceEventNotifier* event_notifier) 28 ApiResourceEventNotifier* event_notifier,
29 bool is_connected)
24 : Socket(event_notifier), 30 : Socket(event_notifier),
25 socket_(tcp_client_socket) { 31 socket_(tcp_client_socket),
32 is_client_socket_(true),
33 is_server_socket_(false) {
34 this->is_connected_ = is_connected;
35 }
36
37 TCPSocket::TCPSocket(net::TCPServerSocket* tcp_server_socket)
38 : Socket(NULL),
39 server_socket_(tcp_server_socket),
40 is_client_socket_(false),
41 is_server_socket_(true) {
26 } 42 }
27 43
28 // static 44 // static
29 TCPSocket* TCPSocket::CreateSocketForTesting( 45 TCPSocket* TCPSocket::CreateSocketForTesting(
30 net::TCPClientSocket* tcp_client_socket, 46 net::TCPClientSocket* tcp_client_socket,
31 ApiResourceEventNotifier* event_notifier) { 47 ApiResourceEventNotifier* event_notifier) {
32 return new TCPSocket(tcp_client_socket, event_notifier); 48 return new TCPSocket(tcp_client_socket, event_notifier);
33 } 49 }
34 50
51 // static
52 TCPSocket* TCPSocket::CreateServerSocketForTesting(
53 net::TCPServerSocket* tcp_server_socket) {
54 return new TCPSocket(tcp_server_socket);
55 }
56
35 TCPSocket::~TCPSocket() { 57 TCPSocket::~TCPSocket() {
36 if (is_connected_) { 58 if (is_connected_) {
37 Disconnect(); 59 Disconnect();
38 } 60 }
61 server_socket_.reset(NULL);
39 } 62 }
40 63
41 void TCPSocket::Connect(const std::string& address, 64 void TCPSocket::Connect(const std::string& address,
42 int port, 65 int port,
43 const CompletionCallback& callback) { 66 const CompletionCallback& callback) {
44 DCHECK(!callback.is_null()); 67 DCHECK(!callback.is_null());
45 68
46 if (!connect_callback_.is_null()) { 69 if (!connect_callback_.is_null() || is_server_socket_) {
47 callback.Run(net::ERR_CONNECTION_FAILED); 70 callback.Run(net::ERR_CONNECTION_FAILED);
48 return; 71 return;
49 } 72 }
73 DCHECK(server_socket_.get() == NULL);
Peng 2012/09/11 14:01:18 DCHECK(!server_socket_.get())
justinlin 2012/09/12 07:29:42 Done.
74 is_client_socket_ = true;
50 connect_callback_ = callback; 75 connect_callback_ = callback;
51 76
52 int result = net::ERR_CONNECTION_FAILED; 77 int result = net::ERR_CONNECTION_FAILED;
53 do { 78 do {
54 if (is_connected_) 79 if (is_connected_)
55 break; 80 break;
56 81
57 net::AddressList address_list; 82 net::AddressList address_list;
58 if (!StringAndPortToAddressList(address, port, &address_list)) { 83 if (!StringAndPortToAddressList(address, port, &address_list)) {
59 result = net::ERR_ADDRESS_INVALID; 84 result = net::ERR_ADDRESS_INVALID;
60 break; 85 break;
61 } 86 }
62 87
63 socket_.reset(new net::TCPClientSocket(address_list, NULL, 88 socket_.reset(new net::TCPClientSocket(address_list, NULL,
64 net::NetLog::Source())); 89 net::NetLog::Source()));
90
91 if (bind_address_.get() != NULL) {
Peng 2012/09/11 14:01:18 if(bind_address_.get())
justinlin 2012/09/12 07:29:42 Done.
92 if (socket_->Bind(*bind_address_) != 0) {
Peng 2012/09/11 14:01:18 Is there an ERR code for 0? like net::OK
justinlin 2012/09/12 07:29:42 The function explicitly just returns 0, but net::O
93 socket_.reset();
94 OnConnectComplete(net::ERR_ADDRESS_IN_USE);
95 return;
96 };
97 }
98
65 connect_callback_ = callback; 99 connect_callback_ = callback;
66 result = socket_->Connect(base::Bind( 100 result = socket_->Connect(base::Bind(
67 &TCPSocket::OnConnectComplete, base::Unretained(this))); 101 &TCPSocket::OnConnectComplete, base::Unretained(this)));
68 } while (false); 102 } while (false);
69 103
70 if (result != net::ERR_IO_PENDING) 104 if (result != net::ERR_IO_PENDING)
71 OnConnectComplete(result); 105 OnConnectComplete(result);
72 } 106 }
73 107
74 void TCPSocket::Disconnect() { 108 void TCPSocket::Disconnect() {
75 is_connected_ = false; 109 is_connected_ = false;
76 socket_->Disconnect(); 110 socket_->Disconnect();
77 } 111 }
78 112
79 int TCPSocket::Bind(const std::string& address, int port) { 113 int TCPSocket::Bind(const std::string& address, int port) {
80 // TODO(penghuang): Supports bind for tcp? 114 if (bind_address_.get() != NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
81 return net::ERR_FAILED; 115 return net::ERR_FAILED;
116 }
117
118 scoped_ptr<net::IPEndPoint> ip_end_point(new net::IPEndPoint());
119 if (!StringAndPortToIPEndPoint(address, port, ip_end_point.get()))
120 return net::ERR_INVALID_ARGUMENT;
121
122 bind_address_.swap(ip_end_point);
123 return net::OK;
82 } 124 }
83 125
84 void TCPSocket::Read(int count, 126 void TCPSocket::Read(int count,
85 const ReadCompletionCallback& callback) { 127 const ReadCompletionCallback& callback) {
86 DCHECK(!callback.is_null()); 128 DCHECK(!callback.is_null());
87 129
130 if (!is_client_socket_) {
131 callback.Run(net::ERR_FAILED, NULL);
132 return;
133 }
134
88 if (!read_callback_.is_null()) { 135 if (!read_callback_.is_null()) {
89 callback.Run(net::ERR_IO_PENDING, NULL); 136 callback.Run(net::ERR_IO_PENDING, NULL);
90 return; 137 return;
91 } else { 138 } else {
92 read_callback_ = callback; 139 read_callback_ = callback;
93 } 140 }
94 141
95 int result = net::ERR_FAILED; 142 int result = net::ERR_FAILED;
96 scoped_refptr<net::IOBuffer> io_buffer; 143 scoped_refptr<net::IOBuffer> io_buffer;
97 do { 144 do {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 return false; 180 return false;
134 return socket_->SetKeepAlive(enable, delay); 181 return socket_->SetKeepAlive(enable, delay);
135 } 182 }
136 183
137 bool TCPSocket::SetNoDelay(bool no_delay) { 184 bool TCPSocket::SetNoDelay(bool no_delay) {
138 if (!socket_.get()) 185 if (!socket_.get())
139 return false; 186 return false;
140 return socket_->SetNoDelay(no_delay); 187 return socket_->SetNoDelay(no_delay);
141 } 188 }
142 189
190 int TCPSocket::Listen(int backlog, std::string& error_msg) {
Peng 2012/09/11 14:01:18 I remember our coding style recommend to use poin
justinlin 2012/09/12 07:29:42 Done.
191 if (is_client_socket_) {
192 error_msg = kTCPSocketTypeInvalidError;
193 return net::ERR_NOT_IMPLEMENTED;
194 }
195 DCHECK(socket_.get() == NULL);
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
196 is_server_socket_ = true;
197
198 if (bind_address_.get() == NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
199 return net::ERR_FAILED;
200 }
201
202 if (server_socket_.get() == NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
203 server_socket_.reset(new net::TCPServerSocket(NULL,
204 net::NetLog::Source()));
205 }
206 int result = server_socket_->Listen(*bind_address_, backlog);
207 if (result != 0) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
208 error_msg = kSocketListenError;
209 }
210 return result;
211 }
212
213 void TCPSocket::Accept(const AcceptCompletionCallback &callback) {
214 if (!is_server_socket_ || server_socket_.get() == NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
215 callback.Run(net::ERR_FAILED, NULL);
216 return;
217 }
218
219 // Limits to only 1 blocked accept call.
220 if (!accept_callback_.is_null()) {
221 callback.Run(net::ERR_FAILED, NULL);
222 return;
223 }
224
225 int result = server_socket_->Accept(&accept_socket_, base::Bind(
226 &TCPSocket::OnAccept, base::Unretained(this)));
227 if (result == net::ERR_IO_PENDING) {
228 accept_callback_ = callback;
229 return;
230 } else if (result == net::OK) {
231 accept_callback_ = callback;
232 this->OnAccept(result);
233 return;
234 } else {
235 callback.Run(result, NULL);
236 return;
237 }
238 }
239
143 bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) { 240 bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) {
144 if (!socket_.get()) 241 if (!socket_.get())
145 return false; 242 return false;
146 return !socket_->GetPeerAddress(address); 243 return !socket_->GetPeerAddress(address);
147 } 244 }
148 245
149 bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) { 246 bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) {
150 if (!socket_.get()) 247 if (socket_.get() != NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
248 return !socket_->GetLocalAddress(address);
249 } else if (server_socket_.get() != NULL) {
Peng 2012/09/11 14:01:18 ditto
justinlin 2012/09/12 07:29:42 Done.
250 return !server_socket_->GetLocalAddress(address);
251 } else {
151 return false; 252 return false;
152 return !socket_->GetLocalAddress(address); 253 }
153 } 254 }
154 255
155 Socket::SocketType TCPSocket::GetSocketType() const { 256 Socket::SocketType TCPSocket::GetSocketType() const {
156 return Socket::TYPE_TCP; 257 return Socket::TYPE_TCP;
157 } 258 }
158 259
159 int TCPSocket::WriteImpl(net::IOBuffer* io_buffer, 260 int TCPSocket::WriteImpl(net::IOBuffer* io_buffer,
160 int io_buffer_size, 261 int io_buffer_size,
161 const net::CompletionCallback& callback) { 262 const net::CompletionCallback& callback) {
162 if (!socket_.get() || !socket_->IsConnected()) 263 if (!is_client_socket_)
264 return net::ERR_FAILED;
265 else if (!socket_.get() || !socket_->IsConnected())
163 return net::ERR_SOCKET_NOT_CONNECTED; 266 return net::ERR_SOCKET_NOT_CONNECTED;
164 else 267 else
165 return socket_->Write(io_buffer, io_buffer_size, callback); 268 return socket_->Write(io_buffer, io_buffer_size, callback);
166 } 269 }
167 270
168 void TCPSocket::OnConnectComplete(int result) { 271 void TCPSocket::OnConnectComplete(int result) {
169 DCHECK(!connect_callback_.is_null()); 272 DCHECK(!connect_callback_.is_null());
170 DCHECK(!is_connected_); 273 DCHECK(!is_connected_);
171 is_connected_ = result == net::OK; 274 is_connected_ = result == net::OK;
172 connect_callback_.Run(result); 275 connect_callback_.Run(result);
173 connect_callback_.Reset(); 276 connect_callback_.Reset();
174 } 277 }
175 278
176 void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, 279 void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
177 int result) { 280 int result) {
178 DCHECK(!read_callback_.is_null()); 281 DCHECK(!read_callback_.is_null());
179 read_callback_.Run(result, io_buffer); 282 read_callback_.Run(result, io_buffer);
180 read_callback_.Reset(); 283 read_callback_.Reset();
181 } 284 }
182 285
286 void TCPSocket::OnAccept(int result) {
287 DCHECK(!accept_callback_.is_null());
288 if (result == net::OK) {
289 DCHECK(accept_socket_.get() != NULL);
290
291 accept_callback_.Run(
292 result, static_cast<net::TCPClientSocket*>(accept_socket_.release()));
293 } else {
294 accept_callback_.Run(result, NULL);
295 }
296 accept_callback_.Reset();
297 }
298
183 } // namespace extensions 299 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698