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 |