OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "net/base/tcp_client_socket.h" | 5 #include "net/base/tcp_client_socket.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <netdb.h> | 9 #include <netdb.h> |
10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
11 | 11 |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/string_util.h" |
| 14 #include "base/trace_event.h" |
13 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
14 #include "third_party/libevent/event.h" | 16 #include "third_party/libevent/event.h" |
15 | 17 |
16 | 18 |
17 namespace net { | 19 namespace net { |
18 | 20 |
19 const int kInvalidSocket = -1; | 21 const int kInvalidSocket = -1; |
20 | 22 |
21 // Return 0 on success, -1 on failure. | 23 // Return 0 on success, -1 on failure. |
22 // Too small a function to bother putting in a library? | 24 // Too small a function to bother putting in a library? |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 Disconnect(); | 78 Disconnect(); |
77 } | 79 } |
78 | 80 |
79 int TCPClientSocket::Connect(CompletionCallback* callback) { | 81 int TCPClientSocket::Connect(CompletionCallback* callback) { |
80 // If already connected, then just return OK. | 82 // If already connected, then just return OK. |
81 if (socket_ != kInvalidSocket) | 83 if (socket_ != kInvalidSocket) |
82 return OK; | 84 return OK; |
83 | 85 |
84 DCHECK(!waiting_connect_); | 86 DCHECK(!waiting_connect_); |
85 | 87 |
| 88 TRACE_EVENT_BEGIN("socket.connect", this, ""); |
86 const addrinfo* ai = current_ai_; | 89 const addrinfo* ai = current_ai_; |
87 DCHECK(ai); | 90 DCHECK(ai); |
88 | 91 |
89 int rv = CreateSocket(ai); | 92 int rv = CreateSocket(ai); |
90 if (rv != OK) | 93 if (rv != OK) |
91 return rv; | 94 return rv; |
92 | 95 |
93 if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) { | 96 if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) { |
| 97 TRACE_EVENT_END("socket.connect", this, ""); |
94 // Connected without waiting! | 98 // Connected without waiting! |
95 return OK; | 99 return OK; |
96 } | 100 } |
97 | 101 |
98 // Synchronous operation not supported | 102 // Synchronous operation not supported |
99 DCHECK(callback); | 103 DCHECK(callback); |
100 | 104 |
101 if (errno != EINPROGRESS) { | 105 if (errno != EINPROGRESS) { |
102 DLOG(INFO) << "connect failed: " << errno; | 106 DLOG(INFO) << "connect failed: " << errno; |
103 close(socket_); | 107 close(socket_); |
(...skipping 20 matching lines...) Expand all Loading... |
124 | 128 |
125 int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) { | 129 int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) { |
126 // No ignorable errors! | 130 // No ignorable errors! |
127 return ERR_UNEXPECTED; | 131 return ERR_UNEXPECTED; |
128 } | 132 } |
129 | 133 |
130 void TCPClientSocket::Disconnect() { | 134 void TCPClientSocket::Disconnect() { |
131 if (socket_ == kInvalidSocket) | 135 if (socket_ == kInvalidSocket) |
132 return; | 136 return; |
133 | 137 |
| 138 TRACE_EVENT_INSTANT("socket.disconnect", this, ""); |
| 139 |
134 socket_watcher_.StopWatchingFileDescriptor(); | 140 socket_watcher_.StopWatchingFileDescriptor(); |
135 close(socket_); | 141 close(socket_); |
136 socket_ = kInvalidSocket; | 142 socket_ = kInvalidSocket; |
137 waiting_connect_ = false; | 143 waiting_connect_ = false; |
138 | 144 |
139 // Reset for next time. | 145 // Reset for next time. |
140 current_ai_ = addresses_.head(); | 146 current_ai_ = addresses_.head(); |
141 } | 147 } |
142 | 148 |
143 bool TCPClientSocket::IsConnected() const { | 149 bool TCPClientSocket::IsConnected() const { |
(...skipping 14 matching lines...) Expand all Loading... |
158 int TCPClientSocket::Read(char* buf, | 164 int TCPClientSocket::Read(char* buf, |
159 int buf_len, | 165 int buf_len, |
160 CompletionCallback* callback) { | 166 CompletionCallback* callback) { |
161 DCHECK(socket_ != kInvalidSocket); | 167 DCHECK(socket_ != kInvalidSocket); |
162 DCHECK(!waiting_connect_); | 168 DCHECK(!waiting_connect_); |
163 DCHECK(!callback_); | 169 DCHECK(!callback_); |
164 // Synchronous operation not supported | 170 // Synchronous operation not supported |
165 DCHECK(callback); | 171 DCHECK(callback); |
166 DCHECK(buf_len > 0); | 172 DCHECK(buf_len > 0); |
167 | 173 |
| 174 TRACE_EVENT_BEGIN("socket.read", this, ""); |
168 int nread = read(socket_, buf, buf_len); | 175 int nread = read(socket_, buf, buf_len); |
169 if (nread >= 0) { | 176 if (nread >= 0) { |
| 177 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", nread)); |
170 return nread; | 178 return nread; |
171 } | 179 } |
172 if (errno != EAGAIN && errno != EWOULDBLOCK) { | 180 if (errno != EAGAIN && errno != EWOULDBLOCK) { |
173 DLOG(INFO) << "read failed, errno " << errno; | 181 DLOG(INFO) << "read failed, errno " << errno; |
174 return MapPosixError(errno); | 182 return MapPosixError(errno); |
175 } | 183 } |
176 | 184 |
177 if (!MessageLoopForIO::current()->WatchFileDescriptor( | 185 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
178 socket_, true, MessageLoopForIO::WATCH_READ, &socket_watcher_, this)) | 186 socket_, true, MessageLoopForIO::WATCH_READ, &socket_watcher_, this)) |
179 { | 187 { |
(...skipping 10 matching lines...) Expand all Loading... |
190 int TCPClientSocket::Write(const char* buf, | 198 int TCPClientSocket::Write(const char* buf, |
191 int buf_len, | 199 int buf_len, |
192 CompletionCallback* callback) { | 200 CompletionCallback* callback) { |
193 DCHECK(socket_ != kInvalidSocket); | 201 DCHECK(socket_ != kInvalidSocket); |
194 DCHECK(!waiting_connect_); | 202 DCHECK(!waiting_connect_); |
195 DCHECK(!write_callback_); | 203 DCHECK(!write_callback_); |
196 // Synchronous operation not supported | 204 // Synchronous operation not supported |
197 DCHECK(callback); | 205 DCHECK(callback); |
198 DCHECK(buf_len > 0); | 206 DCHECK(buf_len > 0); |
199 | 207 |
| 208 TRACE_EVENT_BEGIN("socket.write", this, ""); |
200 int nwrite = write(socket_, buf, buf_len); | 209 int nwrite = write(socket_, buf, buf_len); |
201 if (nwrite >= 0) { | 210 if (nwrite >= 0) { |
| 211 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", nwrite)); |
202 return nwrite; | 212 return nwrite; |
203 } | 213 } |
204 if (errno != EAGAIN && errno != EWOULDBLOCK) | 214 if (errno != EAGAIN && errno != EWOULDBLOCK) |
205 return MapPosixError(errno); | 215 return MapPosixError(errno); |
206 | 216 |
207 if (!MessageLoopForIO::current()->WatchFileDescriptor( | 217 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
208 socket_, true, MessageLoopForIO::WATCH_WRITE, &socket_watcher_, this)) | 218 socket_, true, MessageLoopForIO::WATCH_WRITE, &socket_watcher_, this)) |
209 { | 219 { |
210 DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; | 220 DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; |
211 return MapPosixError(errno); | 221 return MapPosixError(errno); |
212 } | 222 } |
213 | 223 |
214 | 224 |
215 write_buf_ = buf; | 225 write_buf_ = buf; |
216 write_buf_len_ = buf_len; | 226 write_buf_len_ = buf_len; |
217 write_callback_ = callback; | 227 write_callback_ = callback; |
218 return ERR_IO_PENDING; | 228 return ERR_IO_PENDING; |
219 } | 229 } |
220 | 230 |
221 int TCPClientSocket::CreateSocket(const addrinfo* ai) { | 231 int TCPClientSocket::CreateSocket(const addrinfo* ai) { |
222 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); | 232 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
223 if (socket_ == kInvalidSocket) | 233 if (socket_ == kInvalidSocket) |
224 return MapPosixError(errno); | 234 return MapPosixError(errno); |
225 | 235 |
226 // All our socket I/O is nonblocking | |
227 if (SetNonBlocking(socket_)) | 236 if (SetNonBlocking(socket_)) |
228 return MapPosixError(errno); | 237 return MapPosixError(errno); |
229 | 238 |
230 return OK; | 239 return OK; |
231 } | 240 } |
232 | 241 |
233 void TCPClientSocket::DoCallback(int rv) { | 242 void TCPClientSocket::DoCallback(int rv) { |
234 DCHECK(rv != ERR_IO_PENDING); | 243 DCHECK(rv != ERR_IO_PENDING); |
235 DCHECK(callback_); | 244 DCHECK(callback_); |
236 | 245 |
237 // since Run may result in Read being called, clear callback_ up front. | 246 // since Run may result in Read being called, clear callback_ up front. |
238 CompletionCallback* c = callback_; | 247 CompletionCallback* c = callback_; |
239 callback_ = NULL; | 248 callback_ = NULL; |
240 c->Run(rv); | 249 c->Run(rv); |
241 } | 250 } |
242 | 251 |
243 void TCPClientSocket::DoWriteCallback(int rv) { | 252 void TCPClientSocket::DoWriteCallback(int rv) { |
244 DCHECK(rv != ERR_IO_PENDING); | 253 DCHECK(rv != ERR_IO_PENDING); |
245 DCHECK(write_callback_); | 254 DCHECK(write_callback_); |
246 | 255 |
247 // since Run may result in Write being called, clear write_callback_ up front. | 256 // since Run may result in Write being called, clear write_callback_ up front. |
248 CompletionCallback* c = write_callback_; | 257 CompletionCallback* c = write_callback_; |
249 write_callback_ = NULL; | 258 write_callback_ = NULL; |
250 c->Run(rv); | 259 c->Run(rv); |
251 } | 260 } |
252 | 261 |
253 void TCPClientSocket::DidCompleteConnect() { | 262 void TCPClientSocket::DidCompleteConnect() { |
254 int result = ERR_UNEXPECTED; | 263 int result = ERR_UNEXPECTED; |
255 | 264 |
| 265 TRACE_EVENT_END("socket.connect", this, ""); |
| 266 |
256 // Check to see if connect succeeded | 267 // Check to see if connect succeeded |
257 int error_code = 0; | 268 int error_code = 0; |
258 socklen_t len = sizeof(error_code); | 269 socklen_t len = sizeof(error_code); |
259 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &error_code, &len) < 0) | 270 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &error_code, &len) < 0) |
260 error_code = errno; | 271 error_code = errno; |
261 | 272 |
262 if (error_code == EINPROGRESS || error_code == EALREADY) { | 273 if (error_code == EINPROGRESS || error_code == EALREADY) { |
263 NOTREACHED(); // This indicates a bug in libevent or our code. | 274 NOTREACHED(); // This indicates a bug in libevent or our code. |
264 result = ERR_IO_PENDING; | 275 result = ERR_IO_PENDING; |
265 } else if (current_ai_->ai_next && ( | 276 } else if (current_ai_->ai_next && ( |
(...skipping 18 matching lines...) Expand all Loading... |
284 DoCallback(result); | 295 DoCallback(result); |
285 } | 296 } |
286 } | 297 } |
287 | 298 |
288 void TCPClientSocket::DidCompleteRead() { | 299 void TCPClientSocket::DidCompleteRead() { |
289 int bytes_transferred; | 300 int bytes_transferred; |
290 bytes_transferred = read(socket_, buf_, buf_len_); | 301 bytes_transferred = read(socket_, buf_, buf_len_); |
291 | 302 |
292 int result; | 303 int result; |
293 if (bytes_transferred >= 0) { | 304 if (bytes_transferred >= 0) { |
| 305 TRACE_EVENT_END("socket.read", this, |
| 306 StringPrintf("%d bytes", bytes_transferred)); |
294 result = bytes_transferred; | 307 result = bytes_transferred; |
295 } else { | 308 } else { |
296 result = MapPosixError(errno); | 309 result = MapPosixError(errno); |
297 } | 310 } |
298 | 311 |
299 if (result != ERR_IO_PENDING) { | 312 if (result != ERR_IO_PENDING) { |
300 buf_ = NULL; | 313 buf_ = NULL; |
301 buf_len_ = 0; | 314 buf_len_ = 0; |
302 socket_watcher_.StopWatchingFileDescriptor(); | 315 socket_watcher_.StopWatchingFileDescriptor(); |
303 DoCallback(result); | 316 DoCallback(result); |
304 } | 317 } |
305 } | 318 } |
306 | 319 |
307 void TCPClientSocket::DidCompleteWrite() { | 320 void TCPClientSocket::DidCompleteWrite() { |
308 int bytes_transferred; | 321 int bytes_transferred; |
309 bytes_transferred = write(socket_, write_buf_, write_buf_len_); | 322 bytes_transferred = write(socket_, write_buf_, write_buf_len_); |
310 | 323 |
311 int result; | 324 int result; |
312 if (bytes_transferred >= 0) { | 325 if (bytes_transferred >= 0) { |
313 result = bytes_transferred; | 326 result = bytes_transferred; |
| 327 TRACE_EVENT_END("socket.write", this, |
| 328 StringPrintf("%d bytes", bytes_transferred)); |
314 } else { | 329 } else { |
315 result = MapPosixError(errno); | 330 result = MapPosixError(errno); |
316 } | 331 } |
317 | 332 |
318 if (result != ERR_IO_PENDING) { | 333 if (result != ERR_IO_PENDING) { |
319 write_buf_ = NULL; | 334 write_buf_ = NULL; |
320 write_buf_len_ = 0; | 335 write_buf_len_ = 0; |
321 socket_watcher_.StopWatchingFileDescriptor(); | 336 socket_watcher_.StopWatchingFileDescriptor(); |
322 DoWriteCallback(result); | 337 DoWriteCallback(result); |
323 } | 338 } |
(...skipping 14 matching lines...) Expand all Loading... |
338 DidCompleteWrite(); | 353 DidCompleteWrite(); |
339 } | 354 } |
340 } | 355 } |
341 | 356 |
342 int TCPClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { | 357 int TCPClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { |
343 return ::getpeername(socket_, name, namelen); | 358 return ::getpeername(socket_, name, namelen); |
344 } | 359 } |
345 | 360 |
346 } // namespace net | 361 } // namespace net |
347 | 362 |
OLD | NEW |