| 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> |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 | 63 |
| 64 //----------------------------------------------------------------------------- | 64 //----------------------------------------------------------------------------- |
| 65 | 65 |
| 66 TCPClientSocket::TCPClientSocket(const AddressList& addresses) | 66 TCPClientSocket::TCPClientSocket(const AddressList& addresses) |
| 67 : socket_(kInvalidSocket), | 67 : socket_(kInvalidSocket), |
| 68 addresses_(addresses), | 68 addresses_(addresses), |
| 69 current_ai_(addresses_.head()), | 69 current_ai_(addresses_.head()), |
| 70 waiting_connect_(false), | 70 waiting_connect_(false), |
| 71 event_(new event), | |
| 72 write_callback_(NULL), | 71 write_callback_(NULL), |
| 73 callback_(NULL) { | 72 callback_(NULL) { |
| 74 } | 73 } |
| 75 | 74 |
| 76 TCPClientSocket::~TCPClientSocket() { | 75 TCPClientSocket::~TCPClientSocket() { |
| 77 Disconnect(); | 76 Disconnect(); |
| 78 } | 77 } |
| 79 | 78 |
| 80 int TCPClientSocket::Connect(CompletionCallback* callback) { | 79 int TCPClientSocket::Connect(CompletionCallback* callback) { |
| 81 // If already connected, then just return OK. | 80 // If already connected, then just return OK. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 99 // Synchronous operation not supported | 98 // Synchronous operation not supported |
| 100 DCHECK(callback); | 99 DCHECK(callback); |
| 101 | 100 |
| 102 if (errno != EINPROGRESS) { | 101 if (errno != EINPROGRESS) { |
| 103 DLOG(INFO) << "connect failed: " << errno; | 102 DLOG(INFO) << "connect failed: " << errno; |
| 104 close(socket_); | 103 close(socket_); |
| 105 socket_ = kInvalidSocket; | 104 socket_ = kInvalidSocket; |
| 106 return MapPosixError(errno); | 105 return MapPosixError(errno); |
| 107 } | 106 } |
| 108 | 107 |
| 109 // Initialize event_ and link it to our MessagePump. | 108 // Initialize socket_watcher_ and link it to our MessagePump. |
| 110 // POLLOUT is set if the connection is established. | 109 // POLLOUT is set if the connection is established. |
| 111 // POLLIN is set if the connection fails, | 110 // POLLIN is set if the connection fails. |
| 112 // so select for both read and write. | 111 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
| 113 MessageLoopForIO::current()->WatchSocket( | 112 socket_, true, MessageLoopForIO::WATCH_WRITE, &socket_watcher_, |
| 114 socket_, EV_READ|EV_WRITE|EV_PERSIST, event_.get(), this); | 113 this)) { |
| 114 DLOG(INFO) << "WatchFileDescriptor failed: " << errno; |
| 115 close(socket_); |
| 116 socket_ = kInvalidSocket; |
| 117 return MapPosixError(errno); |
| 118 } |
| 115 | 119 |
| 116 waiting_connect_ = true; | 120 waiting_connect_ = true; |
| 117 callback_ = callback; | 121 callback_ = callback; |
| 118 return ERR_IO_PENDING; | 122 return ERR_IO_PENDING; |
| 119 } | 123 } |
| 120 | 124 |
| 121 int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) { | 125 int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) { |
| 122 // No ignorable errors! | 126 // No ignorable errors! |
| 123 return ERR_UNEXPECTED; | 127 return ERR_UNEXPECTED; |
| 124 } | 128 } |
| 125 | 129 |
| 126 void TCPClientSocket::Disconnect() { | 130 void TCPClientSocket::Disconnect() { |
| 127 if (socket_ == kInvalidSocket) | 131 if (socket_ == kInvalidSocket) |
| 128 return; | 132 return; |
| 129 | 133 |
| 130 MessageLoopForIO::current()->UnwatchSocket(event_.get()); | 134 socket_watcher_.StopWatchingFileDescriptor(); |
| 131 close(socket_); | 135 close(socket_); |
| 132 socket_ = kInvalidSocket; | 136 socket_ = kInvalidSocket; |
| 133 waiting_connect_ = false; | 137 waiting_connect_ = false; |
| 134 | 138 |
| 135 // Reset for next time. | 139 // Reset for next time. |
| 136 current_ai_ = addresses_.head(); | 140 current_ai_ = addresses_.head(); |
| 137 } | 141 } |
| 138 | 142 |
| 139 bool TCPClientSocket::IsConnected() const { | 143 bool TCPClientSocket::IsConnected() const { |
| 140 if (socket_ == kInvalidSocket || waiting_connect_) | 144 if (socket_ == kInvalidSocket || waiting_connect_) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 163 | 167 |
| 164 int nread = read(socket_, buf, buf_len); | 168 int nread = read(socket_, buf, buf_len); |
| 165 if (nread >= 0) { | 169 if (nread >= 0) { |
| 166 return nread; | 170 return nread; |
| 167 } | 171 } |
| 168 if (errno != EAGAIN && errno != EWOULDBLOCK) { | 172 if (errno != EAGAIN && errno != EWOULDBLOCK) { |
| 169 DLOG(INFO) << "read failed, errno " << errno; | 173 DLOG(INFO) << "read failed, errno " << errno; |
| 170 return MapPosixError(errno); | 174 return MapPosixError(errno); |
| 171 } | 175 } |
| 172 | 176 |
| 173 MessageLoopForIO::current()->WatchSocket( | 177 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
| 174 socket_, EV_READ|EV_PERSIST, event_.get(), this); | 178 socket_, true, MessageLoopForIO::WATCH_READ, &socket_watcher_, this)) |
| 179 { |
| 180 DLOG(INFO) << "WatchFileDescriptor failed on read, errno " << errno; |
| 181 return MapPosixError(errno); |
| 182 } |
| 175 | 183 |
| 176 buf_ = buf; | 184 buf_ = buf; |
| 177 buf_len_ = buf_len; | 185 buf_len_ = buf_len; |
| 178 callback_ = callback; | 186 callback_ = callback; |
| 179 return ERR_IO_PENDING; | 187 return ERR_IO_PENDING; |
| 180 } | 188 } |
| 181 | 189 |
| 182 int TCPClientSocket::Write(const char* buf, | 190 int TCPClientSocket::Write(const char* buf, |
| 183 int buf_len, | 191 int buf_len, |
| 184 CompletionCallback* callback) { | 192 CompletionCallback* callback) { |
| 185 DCHECK(socket_ != kInvalidSocket); | 193 DCHECK(socket_ != kInvalidSocket); |
| 186 DCHECK(!waiting_connect_); | 194 DCHECK(!waiting_connect_); |
| 187 DCHECK(!write_callback_); | 195 DCHECK(!write_callback_); |
| 188 // Synchronous operation not supported | 196 // Synchronous operation not supported |
| 189 DCHECK(callback); | 197 DCHECK(callback); |
| 190 DCHECK(buf_len > 0); | 198 DCHECK(buf_len > 0); |
| 191 | 199 |
| 192 int nwrite = write(socket_, buf, buf_len); | 200 int nwrite = write(socket_, buf, buf_len); |
| 193 if (nwrite >= 0) { | 201 if (nwrite >= 0) { |
| 194 return nwrite; | 202 return nwrite; |
| 195 } | 203 } |
| 196 if (errno != EAGAIN && errno != EWOULDBLOCK) | 204 if (errno != EAGAIN && errno != EWOULDBLOCK) |
| 197 return MapPosixError(errno); | 205 return MapPosixError(errno); |
| 198 | 206 |
| 199 MessageLoopForIO::current()->WatchSocket( | 207 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
| 200 socket_, EV_WRITE|EV_PERSIST, event_.get(), this); | 208 socket_, true, MessageLoopForIO::WATCH_WRITE, &socket_watcher_, this)) |
| 209 { |
| 210 DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; |
| 211 return MapPosixError(errno); |
| 212 } |
| 213 |
| 201 | 214 |
| 202 write_buf_ = buf; | 215 write_buf_ = buf; |
| 203 write_buf_len_ = buf_len; | 216 write_buf_len_ = buf_len; |
| 204 write_callback_ = callback; | 217 write_callback_ = callback; |
| 205 return ERR_IO_PENDING; | 218 return ERR_IO_PENDING; |
| 206 } | 219 } |
| 207 | 220 |
| 208 int TCPClientSocket::CreateSocket(const addrinfo* ai) { | 221 int TCPClientSocket::CreateSocket(const addrinfo* ai) { |
| 209 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); | 222 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
| 210 if (socket_ == kInvalidSocket) | 223 if (socket_ == kInvalidSocket) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 error_code == ENETUNREACH || | 269 error_code == ENETUNREACH || |
| 257 error_code == EHOSTUNREACH || | 270 error_code == EHOSTUNREACH || |
| 258 error_code == ETIMEDOUT)) { | 271 error_code == ETIMEDOUT)) { |
| 259 // This address failed, try next one in list. | 272 // This address failed, try next one in list. |
| 260 const addrinfo* next = current_ai_->ai_next; | 273 const addrinfo* next = current_ai_->ai_next; |
| 261 Disconnect(); | 274 Disconnect(); |
| 262 current_ai_ = next; | 275 current_ai_ = next; |
| 263 result = Connect(callback_); | 276 result = Connect(callback_); |
| 264 } else { | 277 } else { |
| 265 result = MapPosixError(error_code); | 278 result = MapPosixError(error_code); |
| 266 MessageLoopForIO::current()->UnwatchSocket(event_.get()); | 279 socket_watcher_.StopWatchingFileDescriptor(); |
| 267 waiting_connect_ = false; | 280 waiting_connect_ = false; |
| 268 } | 281 } |
| 269 | 282 |
| 270 if (result != ERR_IO_PENDING) | 283 if (result != ERR_IO_PENDING) { |
| 271 DoCallback(result); | 284 DoCallback(result); |
| 285 } |
| 272 } | 286 } |
| 273 | 287 |
| 274 void TCPClientSocket::DidCompleteRead() { | 288 void TCPClientSocket::DidCompleteRead() { |
| 275 int bytes_transferred; | 289 int bytes_transferred; |
| 276 bytes_transferred = read(socket_, buf_, buf_len_); | 290 bytes_transferred = read(socket_, buf_, buf_len_); |
| 277 | 291 |
| 278 int result; | 292 int result; |
| 279 if (bytes_transferred >= 0) { | 293 if (bytes_transferred >= 0) { |
| 280 result = bytes_transferred; | 294 result = bytes_transferred; |
| 281 } else { | 295 } else { |
| 282 result = MapPosixError(errno); | 296 result = MapPosixError(errno); |
| 283 } | 297 } |
| 284 | 298 |
| 285 if (result != ERR_IO_PENDING) { | 299 if (result != ERR_IO_PENDING) { |
| 286 buf_ = NULL; | 300 buf_ = NULL; |
| 287 buf_len_ = 0; | 301 buf_len_ = 0; |
| 288 MessageLoopForIO::current()->UnwatchSocket(event_.get()); | 302 socket_watcher_.StopWatchingFileDescriptor(); |
| 289 DoCallback(result); | 303 DoCallback(result); |
| 290 } | 304 } |
| 291 } | 305 } |
| 292 | 306 |
| 293 void TCPClientSocket::DidCompleteWrite() { | 307 void TCPClientSocket::DidCompleteWrite() { |
| 294 int bytes_transferred; | 308 int bytes_transferred; |
| 295 bytes_transferred = write(socket_, write_buf_, write_buf_len_); | 309 bytes_transferred = write(socket_, write_buf_, write_buf_len_); |
| 296 | 310 |
| 297 int result; | 311 int result; |
| 298 if (bytes_transferred >= 0) { | 312 if (bytes_transferred >= 0) { |
| 299 result = bytes_transferred; | 313 result = bytes_transferred; |
| 300 } else { | 314 } else { |
| 301 result = MapPosixError(errno); | 315 result = MapPosixError(errno); |
| 302 } | 316 } |
| 303 | 317 |
| 304 if (result != ERR_IO_PENDING) { | 318 if (result != ERR_IO_PENDING) { |
| 305 write_buf_ = NULL; | 319 write_buf_ = NULL; |
| 306 write_buf_len_ = 0; | 320 write_buf_len_ = 0; |
| 307 MessageLoopForIO::current()->UnwatchSocket(event_.get()); | 321 socket_watcher_.StopWatchingFileDescriptor(); |
| 308 DoWriteCallback(result); | 322 DoWriteCallback(result); |
| 309 } | 323 } |
| 310 } | 324 } |
| 311 | 325 |
| 312 void TCPClientSocket::OnSocketReady(short flags) { | 326 void TCPClientSocket::OnFileCanReadWithoutBlocking(int fd) { |
| 313 // the only used bits of flags are EV_READ and EV_WRITE | 327 // When a socket connects it signals both Read and Write, we handle |
| 314 | 328 // DidCompleteConnect() in the write handler. |
| 315 if (waiting_connect_) { | 329 if (!waiting_connect_ && callback_) { |
| 316 DidCompleteConnect(); | 330 DidCompleteRead(); |
| 317 } else { | |
| 318 if ((flags & EV_WRITE) && write_callback_) | |
| 319 DidCompleteWrite(); | |
| 320 if ((flags & EV_READ) && callback_) | |
| 321 DidCompleteRead(); | |
| 322 } | 331 } |
| 323 } | 332 } |
| 324 | 333 |
| 334 void TCPClientSocket::OnFileCanWriteWithoutBlocking(int fd) { |
| 335 if (waiting_connect_) { |
| 336 DidCompleteConnect(); |
| 337 } else if (write_callback_) { |
| 338 DidCompleteWrite(); |
| 339 } |
| 340 } |
| 341 |
| 325 int TCPClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { | 342 int TCPClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { |
| 326 return ::getpeername(socket_, name, namelen); | 343 return ::getpeername(socket_, name, namelen); |
| 327 } | 344 } |
| 328 | 345 |
| 329 } // namespace net | 346 } // namespace net |
| 330 | 347 |
| OLD | NEW |