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 |