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