| 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 |