| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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.h" | 5 #include "net/socket/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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 | 120 |
| 121 //----------------------------------------------------------------------------- | 121 //----------------------------------------------------------------------------- |
| 122 | 122 |
| 123 TCPClientSocketLibevent::TCPClientSocketLibevent( | 123 TCPClientSocketLibevent::TCPClientSocketLibevent( |
| 124 const AddressList& addresses, | 124 const AddressList& addresses, |
| 125 net::NetLog* net_log, | 125 net::NetLog* net_log, |
| 126 const net::NetLog::Source& source) | 126 const net::NetLog::Source& source) |
| 127 : socket_(kInvalidSocket), | 127 : socket_(kInvalidSocket), |
| 128 bound_socket_(kInvalidSocket), | 128 bound_socket_(kInvalidSocket), |
| 129 addresses_(addresses), | 129 addresses_(addresses), |
| 130 current_ai_(NULL), | 130 current_address_index_(-1), |
| 131 read_watcher_(this), | 131 read_watcher_(this), |
| 132 write_watcher_(this), | 132 write_watcher_(this), |
| 133 next_connect_state_(CONNECT_STATE_NONE), | 133 next_connect_state_(CONNECT_STATE_NONE), |
| 134 connect_os_error_(0), | 134 connect_os_error_(0), |
| 135 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), | 135 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), |
| 136 previously_disconnected_(false), | 136 previously_disconnected_(false), |
| 137 use_tcp_fastopen_(false), | 137 use_tcp_fastopen_(false), |
| 138 tcp_fastopen_connected_(false), | 138 tcp_fastopen_connected_(false), |
| 139 num_bytes_read_(0) { | 139 num_bytes_read_(0) { |
| 140 scoped_refptr<NetLog::EventParameters> params; | 140 scoped_refptr<NetLog::EventParameters> params; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 156 | 156 |
| 157 int error = SetupSocket(socket); | 157 int error = SetupSocket(socket); |
| 158 if (error) | 158 if (error) |
| 159 return MapSystemError(error); | 159 return MapSystemError(error); |
| 160 | 160 |
| 161 socket_ = socket; | 161 socket_ = socket; |
| 162 | 162 |
| 163 // This is to make GetPeerAddress() work. It's up to the caller ensure | 163 // This is to make GetPeerAddress() work. It's up to the caller ensure |
| 164 // that |address_| contains a reasonable address for this | 164 // that |address_| contains a reasonable address for this |
| 165 // socket. (i.e. at least match IPv4 vs IPv6!). | 165 // socket. (i.e. at least match IPv4 vs IPv6!). |
| 166 current_ai_ = addresses_.head(); | 166 current_address_index_ = 0; |
| 167 use_history_.set_was_ever_connected(); | 167 use_history_.set_was_ever_connected(); |
| 168 | 168 |
| 169 return OK; | 169 return OK; |
| 170 } | 170 } |
| 171 | 171 |
| 172 int TCPClientSocketLibevent::Bind(const IPEndPoint& address) { | 172 int TCPClientSocketLibevent::Bind(const IPEndPoint& address) { |
| 173 if (current_ai_ != NULL || bind_address_.get()) { | 173 if (current_address_index_ >= 0 || bind_address_.get()) { |
| 174 // Cannot bind the socket if we are already bound connected or | 174 // Cannot bind the socket if we are already bound connected or |
| 175 // connecting. | 175 // connecting. |
| 176 return ERR_UNEXPECTED; | 176 return ERR_UNEXPECTED; |
| 177 } | 177 } |
| 178 | 178 |
| 179 sockaddr_storage addr_storage; | 179 SockaddrStorage storage; |
| 180 sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | 180 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 181 size_t addr_len = sizeof(addr_storage); | |
| 182 if (!address.ToSockAddr(addr, &addr_len)) | |
| 183 return ERR_INVALID_ARGUMENT; | 181 return ERR_INVALID_ARGUMENT; |
| 184 | 182 |
| 185 // Create |bound_socket_| and try to bound it to |address|. | 183 // Create |bound_socket_| and try to bound it to |address|. |
| 186 int error = CreateSocket(address.GetFamily(), &bound_socket_); | 184 int error = CreateSocket(address.GetFamily(), &bound_socket_); |
| 187 if (error) | 185 if (error) |
| 188 return MapSystemError(error); | 186 return MapSystemError(error); |
| 189 | 187 |
| 190 if (HANDLE_EINTR(bind(bound_socket_, addr, addr_len))) { | 188 if (HANDLE_EINTR(bind(bound_socket_, storage.addr, storage.addr_len))) { |
| 191 error = errno; | 189 error = errno; |
| 192 if (HANDLE_EINTR(close(bound_socket_)) < 0) | 190 if (HANDLE_EINTR(close(bound_socket_)) < 0) |
| 193 PLOG(ERROR) << "close"; | 191 PLOG(ERROR) << "close"; |
| 194 bound_socket_ = kInvalidSocket; | 192 bound_socket_ = kInvalidSocket; |
| 195 return MapSystemError(error); | 193 return MapSystemError(error); |
| 196 } | 194 } |
| 197 | 195 |
| 198 bind_address_.reset(new IPEndPoint(address)); | 196 bind_address_.reset(new IPEndPoint(address)); |
| 199 | 197 |
| 200 return 0; | 198 return 0; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 212 | 210 |
| 213 DCHECK(!waiting_connect()); | 211 DCHECK(!waiting_connect()); |
| 214 | 212 |
| 215 net_log_.BeginEvent( | 213 net_log_.BeginEvent( |
| 216 NetLog::TYPE_TCP_CONNECT, | 214 NetLog::TYPE_TCP_CONNECT, |
| 217 make_scoped_refptr(new AddressListNetLogParam(addresses_))); | 215 make_scoped_refptr(new AddressListNetLogParam(addresses_))); |
| 218 | 216 |
| 219 // We will try to connect to each address in addresses_. Start with the | 217 // We will try to connect to each address in addresses_. Start with the |
| 220 // first one in the list. | 218 // first one in the list. |
| 221 next_connect_state_ = CONNECT_STATE_CONNECT; | 219 next_connect_state_ = CONNECT_STATE_CONNECT; |
| 222 current_ai_ = addresses_.head(); | 220 current_address_index_ = 0; |
| 223 | 221 |
| 224 int rv = DoConnectLoop(OK); | 222 int rv = DoConnectLoop(OK); |
| 225 if (rv == ERR_IO_PENDING) { | 223 if (rv == ERR_IO_PENDING) { |
| 226 // Synchronous operation not supported. | 224 // Synchronous operation not supported. |
| 227 DCHECK(!callback.is_null()); | 225 DCHECK(!callback.is_null()); |
| 228 write_callback_ = callback; | 226 write_callback_ = callback; |
| 229 } else { | 227 } else { |
| 230 LogConnectCompletion(rv); | 228 LogConnectCompletion(rv); |
| 231 } | 229 } |
| 232 | 230 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 252 LOG(DFATAL) << "bad state"; | 250 LOG(DFATAL) << "bad state"; |
| 253 rv = ERR_UNEXPECTED; | 251 rv = ERR_UNEXPECTED; |
| 254 break; | 252 break; |
| 255 } | 253 } |
| 256 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE); | 254 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE); |
| 257 | 255 |
| 258 return rv; | 256 return rv; |
| 259 } | 257 } |
| 260 | 258 |
| 261 int TCPClientSocketLibevent::DoConnect() { | 259 int TCPClientSocketLibevent::DoConnect() { |
| 262 DCHECK(current_ai_); | 260 DCHECK_GE(current_address_index_, 0); |
| 261 DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size())); |
| 262 DCHECK_EQ(0, connect_os_error_); |
| 263 | 263 |
| 264 DCHECK_EQ(0, connect_os_error_); | 264 const IPEndPoint& endpoint = addresses_[current_address_index_]; |
| 265 | 265 |
| 266 if (previously_disconnected_) { | 266 if (previously_disconnected_) { |
| 267 use_history_.Reset(); | 267 use_history_.Reset(); |
| 268 previously_disconnected_ = false; | 268 previously_disconnected_ = false; |
| 269 } | 269 } |
| 270 | 270 |
| 271 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, | 271 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, |
| 272 make_scoped_refptr(new NetLogStringParameter( | 272 make_scoped_refptr(new NetLogStringParameter( |
| 273 "address", NetAddressToStringWithPort(current_ai_)))); | 273 "address", |
| 274 endpoint.ToString()))); |
| 274 | 275 |
| 275 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; | 276 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; |
| 276 | 277 |
| 277 if (bound_socket_ != kInvalidSocket) { | 278 if (bound_socket_ != kInvalidSocket) { |
| 278 DCHECK(bind_address_.get()); | 279 DCHECK(bind_address_.get()); |
| 279 socket_ = bound_socket_; | 280 socket_ = bound_socket_; |
| 280 bound_socket_ = kInvalidSocket; | 281 bound_socket_ = kInvalidSocket; |
| 281 } else { | 282 } else { |
| 282 // Create a non-blocking socket. | 283 // Create a non-blocking socket. |
| 283 connect_os_error_ = CreateSocket(current_ai_->ai_family, &socket_); | 284 connect_os_error_ = CreateSocket(endpoint.GetFamily(), &socket_); |
| 284 if (connect_os_error_) | 285 if (connect_os_error_) |
| 285 return MapSystemError(connect_os_error_); | 286 return MapSystemError(connect_os_error_); |
| 286 | 287 |
| 287 if (bind_address_.get()) { | 288 if (bind_address_.get()) { |
| 288 sockaddr_storage addr_storage; | 289 SockaddrStorage storage; |
| 289 sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | 290 if (!bind_address_->ToSockAddr(storage.addr, &storage.addr_len)) |
| 290 size_t addr_len = sizeof(addr_storage); | |
| 291 if (!bind_address_->ToSockAddr(addr, &addr_len)) | |
| 292 return ERR_INVALID_ARGUMENT; | 291 return ERR_INVALID_ARGUMENT; |
| 293 if (HANDLE_EINTR(bind(socket_, addr, addr_len))) | 292 if (HANDLE_EINTR(bind(socket_, storage.addr, storage.addr_len))) |
| 294 return MapSystemError(errno); | 293 return MapSystemError(errno); |
| 295 } | 294 } |
| 296 } | 295 } |
| 297 | 296 |
| 298 // Connect the socket. | 297 // Connect the socket. |
| 299 if (!use_tcp_fastopen_) { | 298 if (!use_tcp_fastopen_) { |
| 299 SockaddrStorage storage; |
| 300 if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len)) |
| 301 return ERR_INVALID_ARGUMENT; |
| 302 |
| 300 connect_start_time_ = base::TimeTicks::Now(); | 303 connect_start_time_ = base::TimeTicks::Now(); |
| 301 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr, | 304 if (!HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len))) { |
| 302 static_cast<int>(current_ai_->ai_addrlen)))) { | |
| 303 // Connected without waiting! | 305 // Connected without waiting! |
| 304 return OK; | 306 return OK; |
| 305 } | 307 } |
| 306 } else { | 308 } else { |
| 307 // With TCP FastOpen, we pretend that the socket is connected. | 309 // With TCP FastOpen, we pretend that the socket is connected. |
| 308 DCHECK(!tcp_fastopen_connected_); | 310 DCHECK(!tcp_fastopen_connected_); |
| 309 return OK; | 311 return OK; |
| 310 } | 312 } |
| 311 | 313 |
| 312 // Check if the connect() failed synchronously. | 314 // Check if the connect() failed synchronously. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 340 connect_time_micros_ = base::TimeTicks::Now() - connect_start_time_; | 342 connect_time_micros_ = base::TimeTicks::Now() - connect_start_time_; |
| 341 write_socket_watcher_.StopWatchingFileDescriptor(); | 343 write_socket_watcher_.StopWatchingFileDescriptor(); |
| 342 use_history_.set_was_ever_connected(); | 344 use_history_.set_was_ever_connected(); |
| 343 return OK; // Done! | 345 return OK; // Done! |
| 344 } | 346 } |
| 345 | 347 |
| 346 // Close whatever partially connected socket we currently have. | 348 // Close whatever partially connected socket we currently have. |
| 347 DoDisconnect(); | 349 DoDisconnect(); |
| 348 | 350 |
| 349 // Try to fall back to the next address in the list. | 351 // Try to fall back to the next address in the list. |
| 350 if (current_ai_->ai_next) { | 352 if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) { |
| 351 next_connect_state_ = CONNECT_STATE_CONNECT; | 353 next_connect_state_ = CONNECT_STATE_CONNECT; |
| 352 current_ai_ = current_ai_->ai_next; | 354 ++current_address_index_; |
| 353 return OK; | 355 return OK; |
| 354 } | 356 } |
| 355 | 357 |
| 356 // Otherwise there is nothing to fall back to, so give up. | 358 // Otherwise there is nothing to fall back to, so give up. |
| 357 return result; | 359 return result; |
| 358 } | 360 } |
| 359 | 361 |
| 360 void TCPClientSocketLibevent::Disconnect() { | 362 void TCPClientSocketLibevent::Disconnect() { |
| 361 DCHECK(CalledOnValidThread()); | 363 DCHECK(CalledOnValidThread()); |
| 362 | 364 |
| 363 DoDisconnect(); | 365 DoDisconnect(); |
| 364 current_ai_ = NULL; | |
| 365 } | 366 } |
| 366 | 367 |
| 367 void TCPClientSocketLibevent::DoDisconnect() { | 368 void TCPClientSocketLibevent::DoDisconnect() { |
| 368 if (socket_ == kInvalidSocket) | 369 if (socket_ == kInvalidSocket) |
| 369 return; | 370 return; |
| 370 | 371 |
| 371 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 372 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
| 372 DCHECK(ok); | 373 DCHECK(ok); |
| 373 ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 374 ok = write_socket_watcher_.StopWatchingFileDescriptor(); |
| 374 DCHECK(ok); | 375 DCHECK(ok); |
| 375 if (HANDLE_EINTR(close(socket_)) < 0) | 376 if (HANDLE_EINTR(close(socket_)) < 0) |
| 376 PLOG(ERROR) << "close"; | 377 PLOG(ERROR) << "close"; |
| 377 socket_ = kInvalidSocket; | 378 socket_ = kInvalidSocket; |
| 378 previously_disconnected_ = true; | 379 previously_disconnected_ = true; |
| 379 } | 380 } |
| 380 | 381 |
| 381 bool TCPClientSocketLibevent::IsConnected() const { | 382 bool TCPClientSocketLibevent::IsConnected() const { |
| 382 DCHECK(CalledOnValidThread()); | 383 DCHECK(CalledOnValidThread()); |
| 383 | 384 |
| 384 if (socket_ == kInvalidSocket || waiting_connect()) | 385 if (socket_ == kInvalidSocket || waiting_connect()) |
| 385 return false; | 386 return false; |
| 386 | 387 |
| 387 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { | 388 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { |
| 388 // With TCP FastOpen, we pretend that the socket is connected. | 389 // With TCP FastOpen, we pretend that the socket is connected. |
| 389 // This allows GetPeerAddress() to return current_ai_ as the peer | 390 // This allows GetPeerAddress() to return current_ai_ as the peer |
| 390 // address. Since we don't fail over to the next address if | 391 // address. Since we don't fail over to the next address if |
| 391 // sendto() fails, current_ai_ is the only possible peer address. | 392 // sendto() fails, current_ai_ is the only possible peer address. |
| 392 CHECK(current_ai_); | 393 CHECK_LT(current_address_index_, static_cast<int>(addresses_.size())); |
| 393 return true; | 394 return true; |
| 394 } | 395 } |
| 395 | 396 |
| 396 // Check if connection is alive. | 397 // Check if connection is alive. |
| 397 char c; | 398 char c; |
| 398 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); | 399 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); |
| 399 if (rv == 0) | 400 if (rv == 0) |
| 400 return false; | 401 return false; |
| 401 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) | 402 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) |
| 402 return false; | 403 return false; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 | 499 |
| 499 write_buf_ = buf; | 500 write_buf_ = buf; |
| 500 write_buf_len_ = buf_len; | 501 write_buf_len_ = buf_len; |
| 501 write_callback_ = callback; | 502 write_callback_ = callback; |
| 502 return ERR_IO_PENDING; | 503 return ERR_IO_PENDING; |
| 503 } | 504 } |
| 504 | 505 |
| 505 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { | 506 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { |
| 506 int nwrite; | 507 int nwrite; |
| 507 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { | 508 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { |
| 509 SockaddrStorage storage; |
| 510 if (!addresses_[current_address_index_].ToSockAddr(storage.addr, |
| 511 &storage.addr_len)) { |
| 512 return ERR_INVALID_ARGUMENT; |
| 513 } |
| 514 |
| 508 // We have a limited amount of data to send in the SYN packet. | 515 // We have a limited amount of data to send in the SYN packet. |
| 509 int kMaxFastOpenSendLength = 1420; | 516 int kMaxFastOpenSendLength = 1420; |
| 510 | 517 |
| 511 buf_len = std::min(kMaxFastOpenSendLength, buf_len); | 518 buf_len = std::min(kMaxFastOpenSendLength, buf_len); |
| 512 | 519 |
| 513 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN | 520 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN |
| 514 nwrite = HANDLE_EINTR(sendto(socket_, | 521 nwrite = HANDLE_EINTR(sendto(socket_, |
| 515 buf->data(), | 522 buf->data(), |
| 516 buf_len, | 523 buf_len, |
| 517 flags, | 524 flags, |
| 518 current_ai_->ai_addr, | 525 storage.addr, |
| 519 static_cast<int>(current_ai_->ai_addrlen))); | 526 storage.addr_len)); |
| 520 tcp_fastopen_connected_ = true; | 527 tcp_fastopen_connected_ = true; |
| 521 | 528 |
| 522 if (nwrite < 0) { | 529 if (nwrite < 0) { |
| 523 // Non-blocking mode is returning EINPROGRESS rather than EAGAIN. | 530 // Non-blocking mode is returning EINPROGRESS rather than EAGAIN. |
| 524 if (errno == EINPROGRESS) | 531 if (errno == EINPROGRESS) |
| 525 errno = EAGAIN; | 532 errno = EAGAIN; |
| 526 | 533 |
| 527 // Unlike "normal" nonblocking sockets, the data is already queued, | 534 // Unlike "normal" nonblocking sockets, the data is already queued, |
| 528 // so tell the app that we've consumed it. | 535 // so tell the app that we've consumed it. |
| 529 return buf_len; | 536 return buf_len; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 554 | 561 |
| 555 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) { | 562 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) { |
| 556 if (net_error == OK) | 563 if (net_error == OK) |
| 557 UpdateConnectionTypeHistograms(CONNECTION_ANY); | 564 UpdateConnectionTypeHistograms(CONNECTION_ANY); |
| 558 | 565 |
| 559 if (net_error != OK) { | 566 if (net_error != OK) { |
| 560 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); | 567 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); |
| 561 return; | 568 return; |
| 562 } | 569 } |
| 563 | 570 |
| 564 struct sockaddr_storage source_address; | 571 SockaddrStorage storage; |
| 565 socklen_t addrlen = sizeof(source_address); | 572 int rv = getsockname(socket_, storage.addr, &storage.addr_len); |
| 566 int rv = getsockname( | |
| 567 socket_, reinterpret_cast<struct sockaddr*>(&source_address), &addrlen); | |
| 568 if (rv != 0) { | 573 if (rv != 0) { |
| 569 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; | 574 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; |
| 570 NOTREACHED(); | 575 NOTREACHED(); |
| 571 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); | 576 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); |
| 572 return; | 577 return; |
| 573 } | 578 } |
| 574 | 579 |
| 575 const std::string source_address_str = | 580 const std::string source_address_str = |
| 576 NetAddressToStringWithPort( | 581 NetAddressToStringWithPort(storage.addr, storage.addr_len); |
| 577 reinterpret_cast<const struct sockaddr*>(&source_address), | |
| 578 sizeof(source_address)); | |
| 579 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, | 582 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, |
| 580 make_scoped_refptr(new NetLogStringParameter( | 583 make_scoped_refptr(new NetLogStringParameter( |
| 581 "source address", | 584 "source address", |
| 582 source_address_str))); | 585 source_address_str))); |
| 583 } | 586 } |
| 584 | 587 |
| 585 void TCPClientSocketLibevent::DoReadCallback(int rv) { | 588 void TCPClientSocketLibevent::DoReadCallback(int rv) { |
| 586 DCHECK_NE(rv, ERR_IO_PENDING); | 589 DCHECK_NE(rv, ERR_IO_PENDING); |
| 587 DCHECK(!read_callback_.is_null()); | 590 DCHECK(!read_callback_.is_null()); |
| 588 | 591 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 write_socket_watcher_.StopWatchingFileDescriptor(); | 680 write_socket_watcher_.StopWatchingFileDescriptor(); |
| 678 DoWriteCallback(result); | 681 DoWriteCallback(result); |
| 679 } | 682 } |
| 680 } | 683 } |
| 681 | 684 |
| 682 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { | 685 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { |
| 683 DCHECK(CalledOnValidThread()); | 686 DCHECK(CalledOnValidThread()); |
| 684 DCHECK(address); | 687 DCHECK(address); |
| 685 if (!IsConnected()) | 688 if (!IsConnected()) |
| 686 return ERR_SOCKET_NOT_CONNECTED; | 689 return ERR_SOCKET_NOT_CONNECTED; |
| 687 *address = AddressList::CreateByCopyingFirstAddress(current_ai_); | 690 *address = AddressList(addresses_[current_address_index_]); |
| 688 return OK; | 691 return OK; |
| 689 } | 692 } |
| 690 | 693 |
| 691 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const { | 694 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const { |
| 692 DCHECK(CalledOnValidThread()); | 695 DCHECK(CalledOnValidThread()); |
| 693 DCHECK(address); | 696 DCHECK(address); |
| 694 if (!IsConnected()) | 697 if (!IsConnected()) |
| 695 return ERR_SOCKET_NOT_CONNECTED; | 698 return ERR_SOCKET_NOT_CONNECTED; |
| 696 | 699 |
| 697 struct sockaddr_storage addr_storage; | 700 SockaddrStorage storage; |
| 698 socklen_t addr_len = sizeof(addr_storage); | 701 if (getsockname(socket_, storage.addr, &storage.addr_len)) |
| 699 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
| 700 if (getsockname(socket_, addr, &addr_len)) | |
| 701 return MapSystemError(errno); | 702 return MapSystemError(errno); |
| 702 if (!address->FromSockAddr(addr, addr_len)) | 703 if (!address->FromSockAddr(storage.addr, storage.addr_len)) |
| 703 return ERR_FAILED; | 704 return ERR_FAILED; |
| 704 | 705 |
| 705 return OK; | 706 return OK; |
| 706 } | 707 } |
| 707 | 708 |
| 708 const BoundNetLog& TCPClientSocketLibevent::NetLog() const { | 709 const BoundNetLog& TCPClientSocketLibevent::NetLog() const { |
| 709 return net_log_; | 710 return net_log_; |
| 710 } | 711 } |
| 711 | 712 |
| 712 void TCPClientSocketLibevent::SetSubresourceSpeculation() { | 713 void TCPClientSocketLibevent::SetSubresourceSpeculation() { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 731 | 732 |
| 732 base::TimeDelta TCPClientSocketLibevent::GetConnectTimeMicros() const { | 733 base::TimeDelta TCPClientSocketLibevent::GetConnectTimeMicros() const { |
| 733 return connect_time_micros_; | 734 return connect_time_micros_; |
| 734 } | 735 } |
| 735 | 736 |
| 736 NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const { | 737 NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const { |
| 737 return kProtoUnknown; | 738 return kProtoUnknown; |
| 738 } | 739 } |
| 739 | 740 |
| 740 } // namespace net | 741 } // namespace net |
| OLD | NEW |