Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(978)

Side by Side Diff: net/socket/tcp_client_socket_libevent.cc

Issue 2132014: Always fallback to the next address when doing TCP connect (libevent impl) (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: sync Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/tcp_client_socket_libevent.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/socket/tcp_client_socket_libevent.h" 5 #include "net/socket/tcp_client_socket_libevent.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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 return ERR_CONNECTION_TIMED_OUT; 94 return ERR_CONNECTION_TIMED_OUT;
95 default: { 95 default: {
96 int net_error = MapPosixError(os_error); 96 int net_error = MapPosixError(os_error);
97 if (net_error == ERR_FAILED) 97 if (net_error == ERR_FAILED)
98 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED. 98 return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
99 return net_error; 99 return net_error;
100 } 100 }
101 } 101 }
102 } 102 }
103 103
104 // Given os_error, an errno from a connect() attempt, returns true if
105 // connect() should be retried with another address.
106 bool ShouldTryNextAddress(int os_error) {
107 switch (os_error) {
108 case EADDRNOTAVAIL:
109 case EAFNOSUPPORT:
110 case ECONNREFUSED:
111 case ECONNRESET:
112 case EACCES:
113 case EPERM:
114 case ENETUNREACH:
115 case EHOSTUNREACH:
116 case ENETDOWN:
117 case ETIMEDOUT:
118 return true;
119 default:
120 return false;
121 }
122 }
123
124 } // namespace 104 } // namespace
125 105
126 //----------------------------------------------------------------------------- 106 //-----------------------------------------------------------------------------
127 107
128 TCPClientSocketLibevent::TCPClientSocketLibevent(const AddressList& addresses, 108 TCPClientSocketLibevent::TCPClientSocketLibevent(const AddressList& addresses,
129 net::NetLog* net_log) 109 net::NetLog* net_log)
130 : socket_(kInvalidSocket), 110 : socket_(kInvalidSocket),
131 addresses_(addresses), 111 addresses_(addresses),
132 current_ai_(addresses_.head()), 112 current_ai_(NULL),
133 waiting_connect_(false),
134 read_watcher_(this), 113 read_watcher_(this),
135 write_watcher_(this), 114 write_watcher_(this),
136 read_callback_(NULL), 115 read_callback_(NULL),
137 write_callback_(NULL), 116 write_callback_(NULL),
117 next_connect_state_(CONNECT_STATE_NONE),
138 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 118 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
139 } 119 }
140 120
141 TCPClientSocketLibevent::~TCPClientSocketLibevent() { 121 TCPClientSocketLibevent::~TCPClientSocketLibevent() {
142 Disconnect(); 122 Disconnect();
143 net_log_.AddEvent(NetLog::TYPE_TCP_SOCKET_DONE, NULL); 123 net_log_.AddEvent(NetLog::TYPE_TCP_SOCKET_DONE, NULL);
144 } 124 }
145 125
146 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) { 126 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) {
147 // If already connected, then just return OK. 127 // If already connected, then just return OK.
148 if (socket_ != kInvalidSocket) 128 if (socket_ != kInvalidSocket)
149 return OK; 129 return OK;
150 130
151 DCHECK(!waiting_connect_); 131 DCHECK(!waiting_connect());
152
153 TRACE_EVENT_BEGIN("socket.connect", this, "");
154 132
155 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, NULL); 133 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, NULL);
156 134
157 int rv = DoConnect(); 135 // We will try to connect to each address in addresses_. Start with the
136 // first one in the list.
137 next_connect_state_ = CONNECT_STATE_CONNECT;
138 current_ai_ = addresses_.head();
158 139
140 int rv = DoConnectLoop(OK);
159 if (rv == ERR_IO_PENDING) { 141 if (rv == ERR_IO_PENDING) {
160 // Synchronous operation not supported. 142 // Synchronous operation not supported.
161 DCHECK(callback); 143 DCHECK(callback);
162
163 waiting_connect_ = true;
164 write_callback_ = callback; 144 write_callback_ = callback;
165 } else { 145 } else {
166 TRACE_EVENT_END("socket.connect", this, "");
167 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, NULL); 146 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, NULL);
168 } 147 }
169 148
170 return rv; 149 return rv;
171 } 150 }
172 151
152 int TCPClientSocketLibevent::DoConnectLoop(int result) {
153 DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
154
155 int rv = result;
156 do {
157 ConnectState state = next_connect_state_;
158 next_connect_state_ = CONNECT_STATE_NONE;
159 switch (state) {
160 case CONNECT_STATE_CONNECT:
161 DCHECK_EQ(OK, rv);
162 rv = DoConnect();
163 break;
164 case CONNECT_STATE_CONNECT_COMPLETE:
165 rv = DoConnectComplete(rv);
166 break;
167 default:
168 LOG(DFATAL) << "bad state";
169 rv = ERR_UNEXPECTED;
170 break;
171 }
172 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
173
174 return rv;
175 }
176
173 int TCPClientSocketLibevent::DoConnect() { 177 int TCPClientSocketLibevent::DoConnect() {
174 while (true) { 178 DCHECK(current_ai_);
175 DCHECK(current_ai_);
176 179
177 int rv = CreateSocket(current_ai_); 180 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
178 if (rv != OK)
179 return rv;
180 181
181 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr, 182 // Create a non-blocking socket.
182 static_cast<int>(current_ai_->ai_addrlen)))) { 183 int os_error = CreateSocket(current_ai_);
183 // Connected without waiting! 184 if (os_error)
184 return OK; 185 return MapPosixError(os_error);
185 }
186 186
187 int os_error = errno; 187 // Connect the socket.
188 if (os_error == EINPROGRESS) 188 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
189 break; 189 static_cast<int>(current_ai_->ai_addrlen)))) {
190 190 // Connected without waiting!
191 close(socket_); 191 return OK;
192 socket_ = kInvalidSocket;
193
194 if (current_ai_->ai_next && ShouldTryNextAddress(os_error)) {
195 // connect() can fail synchronously for an address even on a
196 // non-blocking socket. As an example, this can happen when there is
197 // no route to the host. Retry using the next address in the list.
198 current_ai_ = current_ai_->ai_next;
199 } else {
200 DLOG(INFO) << "connect failed: " << os_error;
201 return MapConnectError(os_error);
202 }
203 } 192 }
204 193
205 // Initialize write_socket_watcher_ and link it to our MessagePump. 194 // Check if the connect() failed synchronously.
206 // POLLOUT is set if the connection is established. 195 os_error = errno;
207 // POLLIN is set if the connection fails. 196 if (os_error != EINPROGRESS)
197 return MapPosixError(os_error);
198
199 // Otherwise the connect() is going to complete asynchronously, so watch
200 // for its completion.
208 if (!MessageLoopForIO::current()->WatchFileDescriptor( 201 if (!MessageLoopForIO::current()->WatchFileDescriptor(
209 socket_, true, MessageLoopForIO::WATCH_WRITE, &write_socket_watcher_, 202 socket_, true, MessageLoopForIO::WATCH_WRITE, &write_socket_watcher_,
210 &write_watcher_)) { 203 &write_watcher_)) {
211 DLOG(INFO) << "WatchFileDescriptor failed: " << errno; 204 DLOG(INFO) << "WatchFileDescriptor failed: " << errno;
212 close(socket_);
213 socket_ = kInvalidSocket;
214 return MapPosixError(errno); 205 return MapPosixError(errno);
215 } 206 }
216 207
217 return ERR_IO_PENDING; 208 return ERR_IO_PENDING;
218 } 209 }
219 210
211 int TCPClientSocketLibevent::DoConnectComplete(int result) {
212 write_socket_watcher_.StopWatchingFileDescriptor();
213
214 if (result == OK)
215 return OK; // Done!
216
217 // Close whatever partially connected socket we currently have.
218 DoDisconnect();
219
220 // Try to fall back to the next address in the list.
221 if (current_ai_->ai_next) {
222 next_connect_state_ = CONNECT_STATE_CONNECT;
223 current_ai_ = current_ai_->ai_next;
224 return OK;
225 }
226
227 // Otherwise there is nothing to fall back to, so give up.
228 return result;
229 }
230
220 void TCPClientSocketLibevent::Disconnect() { 231 void TCPClientSocketLibevent::Disconnect() {
232 DoDisconnect();
233 current_ai_ = NULL;
234 }
235
236 void TCPClientSocketLibevent::DoDisconnect() {
221 if (socket_ == kInvalidSocket) 237 if (socket_ == kInvalidSocket)
222 return; 238 return;
223 239
224 TRACE_EVENT_INSTANT("socket.disconnect", this, "");
225
226 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 240 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
227 DCHECK(ok); 241 DCHECK(ok);
228 ok = write_socket_watcher_.StopWatchingFileDescriptor(); 242 ok = write_socket_watcher_.StopWatchingFileDescriptor();
229 DCHECK(ok); 243 DCHECK(ok);
230 close(socket_); 244 HANDLE_EINTR(close(socket_));
231 socket_ = kInvalidSocket; 245 socket_ = kInvalidSocket;
232 waiting_connect_ = false;
233
234 // Reset for next time.
235 current_ai_ = addresses_.head();
236 } 246 }
237 247
238 bool TCPClientSocketLibevent::IsConnected() const { 248 bool TCPClientSocketLibevent::IsConnected() const {
239 if (socket_ == kInvalidSocket || waiting_connect_) 249 if (socket_ == kInvalidSocket || waiting_connect())
240 return false; 250 return false;
241 251
242 // Check if connection is alive. 252 // Check if connection is alive.
243 char c; 253 char c;
244 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 254 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
245 if (rv == 0) 255 if (rv == 0)
246 return false; 256 return false;
247 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) 257 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
248 return false; 258 return false;
249 259
250 return true; 260 return true;
251 } 261 }
252 262
253 bool TCPClientSocketLibevent::IsConnectedAndIdle() const { 263 bool TCPClientSocketLibevent::IsConnectedAndIdle() const {
254 if (socket_ == kInvalidSocket || waiting_connect_) 264 if (socket_ == kInvalidSocket || waiting_connect())
255 return false; 265 return false;
256 266
257 // Check if connection is alive and we haven't received any data 267 // Check if connection is alive and we haven't received any data
258 // unexpectedly. 268 // unexpectedly.
259 char c; 269 char c;
260 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); 270 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK));
261 if (rv >= 0) 271 if (rv >= 0)
262 return false; 272 return false;
263 if (errno != EAGAIN && errno != EWOULDBLOCK) 273 if (errno != EAGAIN && errno != EWOULDBLOCK)
264 return false; 274 return false;
265 275
266 return true; 276 return true;
267 } 277 }
268 278
269 int TCPClientSocketLibevent::Read(IOBuffer* buf, 279 int TCPClientSocketLibevent::Read(IOBuffer* buf,
270 int buf_len, 280 int buf_len,
271 CompletionCallback* callback) { 281 CompletionCallback* callback) {
272 DCHECK_NE(kInvalidSocket, socket_); 282 DCHECK_NE(kInvalidSocket, socket_);
273 DCHECK(!waiting_connect_); 283 DCHECK(!waiting_connect());
274 DCHECK(!read_callback_); 284 DCHECK(!read_callback_);
275 // Synchronous operation not supported 285 // Synchronous operation not supported
276 DCHECK(callback); 286 DCHECK(callback);
277 DCHECK_GT(buf_len, 0); 287 DCHECK_GT(buf_len, 0);
278 288
279 TRACE_EVENT_BEGIN("socket.read", this, ""); 289 TRACE_EVENT_BEGIN("socket.read", this, "");
280 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len)); 290 int nread = HANDLE_EINTR(read(socket_, buf->data(), buf_len));
281 if (nread >= 0) { 291 if (nread >= 0) {
282 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", nread)); 292 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", nread));
283 net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, 293 net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED,
(...skipping 15 matching lines...) Expand all
299 read_buf_ = buf; 309 read_buf_ = buf;
300 read_buf_len_ = buf_len; 310 read_buf_len_ = buf_len;
301 read_callback_ = callback; 311 read_callback_ = callback;
302 return ERR_IO_PENDING; 312 return ERR_IO_PENDING;
303 } 313 }
304 314
305 int TCPClientSocketLibevent::Write(IOBuffer* buf, 315 int TCPClientSocketLibevent::Write(IOBuffer* buf,
306 int buf_len, 316 int buf_len,
307 CompletionCallback* callback) { 317 CompletionCallback* callback) {
308 DCHECK_NE(kInvalidSocket, socket_); 318 DCHECK_NE(kInvalidSocket, socket_);
309 DCHECK(!waiting_connect_); 319 DCHECK(!waiting_connect());
310 DCHECK(!write_callback_); 320 DCHECK(!write_callback_);
311 // Synchronous operation not supported 321 // Synchronous operation not supported
312 DCHECK(callback); 322 DCHECK(callback);
313 DCHECK_GT(buf_len, 0); 323 DCHECK_GT(buf_len, 0);
314 324
315 TRACE_EVENT_BEGIN("socket.write", this, ""); 325 TRACE_EVENT_BEGIN("socket.write", this, "");
316 int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); 326 int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
317 if (nwrite >= 0) { 327 if (nwrite >= 0) {
318 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", nwrite)); 328 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", nwrite));
319 net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT, 329 net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT,
320 new NetLogIntegerParameter("num_bytes", nwrite)); 330 new NetLogIntegerParameter("num_bytes", nwrite));
321 return nwrite; 331 return nwrite;
322 } 332 }
323 if (errno != EAGAIN && errno != EWOULDBLOCK) 333 if (errno != EAGAIN && errno != EWOULDBLOCK)
324 return MapPosixError(errno); 334 return MapPosixError(errno);
325 335
326 if (!MessageLoopForIO::current()->WatchFileDescriptor( 336 if (!MessageLoopForIO::current()->WatchFileDescriptor(
327 socket_, true, MessageLoopForIO::WATCH_WRITE, 337 socket_, true, MessageLoopForIO::WATCH_WRITE,
328 &write_socket_watcher_, &write_watcher_)) { 338 &write_socket_watcher_, &write_watcher_)) {
329 DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno; 339 DLOG(INFO) << "WatchFileDescriptor failed on write, errno " << errno;
330 return MapPosixError(errno); 340 return MapPosixError(errno);
331 } 341 }
332 342
333
334 write_buf_ = buf; 343 write_buf_ = buf;
335 write_buf_len_ = buf_len; 344 write_buf_len_ = buf_len;
336 write_callback_ = callback; 345 write_callback_ = callback;
337 return ERR_IO_PENDING; 346 return ERR_IO_PENDING;
338 } 347 }
339 348
340 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) { 349 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
341 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 350 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
342 reinterpret_cast<const char*>(&size), 351 reinterpret_cast<const char*>(&size),
343 sizeof(size)); 352 sizeof(size));
344 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 353 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
345 return rv == 0; 354 return rv == 0;
346 } 355 }
347 356
348 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) { 357 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) {
349 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 358 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
350 reinterpret_cast<const char*>(&size), 359 reinterpret_cast<const char*>(&size),
351 sizeof(size)); 360 sizeof(size));
352 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; 361 DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
353 return rv == 0; 362 return rv == 0;
354 } 363 }
355 364
356 365
357 int TCPClientSocketLibevent::CreateSocket(const addrinfo* ai) { 366 int TCPClientSocketLibevent::CreateSocket(const addrinfo* ai) {
358 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 367 socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
359 if (socket_ == kInvalidSocket) 368 if (socket_ == kInvalidSocket)
360 return MapPosixError(errno); 369 return errno;
361 370
362 if (SetNonBlocking(socket_)) { 371 if (SetNonBlocking(socket_)) {
363 const int err = MapPosixError(errno); 372 const int err = errno;
364 close(socket_); 373 close(socket_);
365 socket_ = kInvalidSocket; 374 socket_ = kInvalidSocket;
366 return err; 375 return err;
367 } 376 }
368 377
369 // This mirrors the behaviour on Windows. See the comment in 378 // This mirrors the behaviour on Windows. See the comment in
370 // tcp_client_socket_win.cc after searching for "NODELAY". 379 // tcp_client_socket_win.cc after searching for "NODELAY".
371 DisableNagle(socket_); // If DisableNagle fails, we don't care. 380 DisableNagle(socket_); // If DisableNagle fails, we don't care.
372 381
373 return OK; 382 return 0;
374 } 383 }
375 384
376 void TCPClientSocketLibevent::DoReadCallback(int rv) { 385 void TCPClientSocketLibevent::DoReadCallback(int rv) {
377 DCHECK_NE(rv, ERR_IO_PENDING); 386 DCHECK_NE(rv, ERR_IO_PENDING);
378 DCHECK(read_callback_); 387 DCHECK(read_callback_);
379 388
380 // since Run may result in Read being called, clear read_callback_ up front. 389 // since Run may result in Read being called, clear read_callback_ up front.
381 CompletionCallback* c = read_callback_; 390 CompletionCallback* c = read_callback_;
382 read_callback_ = NULL; 391 read_callback_ = NULL;
383 c->Run(rv); 392 c->Run(rv);
384 } 393 }
385 394
386 void TCPClientSocketLibevent::DoWriteCallback(int rv) { 395 void TCPClientSocketLibevent::DoWriteCallback(int rv) {
387 DCHECK_NE(rv, ERR_IO_PENDING); 396 DCHECK_NE(rv, ERR_IO_PENDING);
388 DCHECK(write_callback_); 397 DCHECK(write_callback_);
389 398
390 // since Run may result in Write being called, clear write_callback_ up front. 399 // since Run may result in Write being called, clear write_callback_ up front.
391 CompletionCallback* c = write_callback_; 400 CompletionCallback* c = write_callback_;
392 write_callback_ = NULL; 401 write_callback_ = NULL;
393 c->Run(rv); 402 c->Run(rv);
394 } 403 }
395 404
396 void TCPClientSocketLibevent::DidCompleteConnect() { 405 void TCPClientSocketLibevent::DidCompleteConnect() {
397 int result = ERR_UNEXPECTED; 406 DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
398 407
399 // Check to see if connect succeeded 408 // Get the error that connect() completed with.
400 int os_error = 0; 409 int os_error = 0;
401 socklen_t len = sizeof(os_error); 410 socklen_t len = sizeof(os_error);
402 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0) 411 if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &os_error, &len) < 0)
403 os_error = errno; 412 os_error = errno;
404 413
414 // TODO(eroman): Is this check really necessary?
405 if (os_error == EINPROGRESS || os_error == EALREADY) { 415 if (os_error == EINPROGRESS || os_error == EALREADY) {
406 NOTREACHED(); // This indicates a bug in libevent or our code. 416 NOTREACHED(); // This indicates a bug in libevent or our code.
407 result = ERR_IO_PENDING; 417 return;
408 } else if (current_ai_->ai_next && ShouldTryNextAddress(os_error)) {
409 // This address failed, try next one in list.
410 const addrinfo* next = current_ai_->ai_next;
411 Disconnect();
412 current_ai_ = next;
413 TRACE_EVENT_END("socket.connect", this, "");
414 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, NULL);
415 result = Connect(write_callback_);
416 } else {
417 result = MapConnectError(os_error);
418 bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
419 DCHECK(ok);
420 waiting_connect_ = false;
421 TRACE_EVENT_END("socket.connect", this, "");
422 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, NULL);
423 } 418 }
424 419
425 if (result != ERR_IO_PENDING) { 420 int rv = DoConnectLoop(MapConnectError(os_error));
426 DoWriteCallback(result); 421 if (rv != ERR_IO_PENDING) {
422 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, NULL);
423 DoWriteCallback(rv);
427 } 424 }
428 } 425 }
429 426
430 void TCPClientSocketLibevent::DidCompleteRead() { 427 void TCPClientSocketLibevent::DidCompleteRead() {
431 int bytes_transferred; 428 int bytes_transferred;
432 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(), 429 bytes_transferred = HANDLE_EINTR(read(socket_, read_buf_->data(),
433 read_buf_len_)); 430 read_buf_len_));
434 431
435 int result; 432 int result;
436 if (bytes_transferred >= 0) { 433 if (bytes_transferred >= 0) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 475
479 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { 476 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const {
480 DCHECK(address); 477 DCHECK(address);
481 if (!current_ai_) 478 if (!current_ai_)
482 return ERR_UNEXPECTED; 479 return ERR_UNEXPECTED;
483 address->Copy(current_ai_, false); 480 address->Copy(current_ai_, false);
484 return OK; 481 return OK;
485 } 482 }
486 483
487 } // namespace net 484 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/tcp_client_socket_libevent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698