Chromium Code Reviews| 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_(static_cast<size_t>(-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_ < addresses_.size() || bind_address_.get()) { |
|
eroman
2012/05/04 01:08:41
If you do my recommendation to change index to an
| |
| 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_, 0u); |
|
eroman
2012/05/04 01:08:41
nit: trivially evaluates to true since index is un
szym
2012/05/04 02:38:29
True. This is a leftover of my first attempt with
| |
| 261 DCHECK_LT(current_address_index_, 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)) | |
|
eroman
2012/05/04 01:08:41
nit: This is duplicated in two locations. How abou
| |
| 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 < addresses_.size()) { |
|
eroman
2012/05/04 01:08:41
The reason I don't like current_address_index bein
| |
| 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; | 366 current_address_index_ = addresses_.size(); |
|
eroman
2012/05/04 01:08:41
This seems unnecessary... I would just delete it i
szym
2012/05/04 02:38:29
I was concerned that it was used to distinguish so
eroman
2012/05/04 19:37:36
Actually sorry, I changed my mind!
I think it wou
| |
| 365 } | 367 } |
| 366 | 368 |
| 367 void TCPClientSocketLibevent::DoDisconnect() { | 369 void TCPClientSocketLibevent::DoDisconnect() { |
| 368 if (socket_ == kInvalidSocket) | 370 if (socket_ == kInvalidSocket) |
| 369 return; | 371 return; |
| 370 | 372 |
| 371 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 373 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
| 372 DCHECK(ok); | 374 DCHECK(ok); |
| 373 ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 375 ok = write_socket_watcher_.StopWatchingFileDescriptor(); |
| 374 DCHECK(ok); | 376 DCHECK(ok); |
| 375 if (HANDLE_EINTR(close(socket_)) < 0) | 377 if (HANDLE_EINTR(close(socket_)) < 0) |
| 376 PLOG(ERROR) << "close"; | 378 PLOG(ERROR) << "close"; |
| 377 socket_ = kInvalidSocket; | 379 socket_ = kInvalidSocket; |
| 378 previously_disconnected_ = true; | 380 previously_disconnected_ = true; |
| 379 } | 381 } |
| 380 | 382 |
| 381 bool TCPClientSocketLibevent::IsConnected() const { | 383 bool TCPClientSocketLibevent::IsConnected() const { |
| 382 DCHECK(CalledOnValidThread()); | 384 DCHECK(CalledOnValidThread()); |
| 383 | 385 |
| 384 if (socket_ == kInvalidSocket || waiting_connect()) | 386 if (socket_ == kInvalidSocket || waiting_connect()) |
| 385 return false; | 387 return false; |
| 386 | 388 |
| 387 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { | 389 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { |
| 388 // With TCP FastOpen, we pretend that the socket is connected. | 390 // With TCP FastOpen, we pretend that the socket is connected. |
| 389 // This allows GetPeerAddress() to return current_ai_ as the peer | 391 // This allows GetPeerAddress() to return current_ai_ as the peer |
| 390 // address. Since we don't fail over to the next address if | 392 // address. Since we don't fail over to the next address if |
| 391 // sendto() fails, current_ai_ is the only possible peer address. | 393 // sendto() fails, current_ai_ is the only possible peer address. |
| 392 CHECK(current_ai_); | 394 CHECK_LT(current_address_index_, addresses_.size()); |
| 393 return true; | 395 return true; |
| 394 } | 396 } |
| 395 | 397 |
| 396 // Check if connection is alive. | 398 // Check if connection is alive. |
| 397 char c; | 399 char c; |
| 398 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); | 400 int rv = HANDLE_EINTR(recv(socket_, &c, 1, MSG_PEEK)); |
| 399 if (rv == 0) | 401 if (rv == 0) |
| 400 return false; | 402 return false; |
| 401 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) | 403 if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK) |
| 402 return false; | 404 return false; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 | 500 |
| 499 write_buf_ = buf; | 501 write_buf_ = buf; |
| 500 write_buf_len_ = buf_len; | 502 write_buf_len_ = buf_len; |
| 501 write_callback_ = callback; | 503 write_callback_ = callback; |
| 502 return ERR_IO_PENDING; | 504 return ERR_IO_PENDING; |
| 503 } | 505 } |
| 504 | 506 |
| 505 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { | 507 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { |
| 506 int nwrite; | 508 int nwrite; |
| 507 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { | 509 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) { |
| 510 SockaddrStorage storage; | |
| 511 if (!addresses_[current_address_index_].ToSockAddr(storage.addr, | |
|
eroman
2012/05/04 01:08:41
I have seen this in a couple places now. I think i
szym
2012/05/04 02:38:29
Not sure. |current_sockaddr_| would need to be a S
| |
| 512 &storage.addr_len)) { | |
| 513 return ERR_INVALID_ARGUMENT; | |
| 514 } | |
| 515 | |
| 508 // We have a limited amount of data to send in the SYN packet. | 516 // We have a limited amount of data to send in the SYN packet. |
| 509 int kMaxFastOpenSendLength = 1420; | 517 int kMaxFastOpenSendLength = 1420; |
| 510 | 518 |
| 511 buf_len = std::min(kMaxFastOpenSendLength, buf_len); | 519 buf_len = std::min(kMaxFastOpenSendLength, buf_len); |
| 512 | 520 |
| 513 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN | 521 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN |
| 514 nwrite = HANDLE_EINTR(sendto(socket_, | 522 nwrite = HANDLE_EINTR(sendto(socket_, |
| 515 buf->data(), | 523 buf->data(), |
| 516 buf_len, | 524 buf_len, |
| 517 flags, | 525 flags, |
| 518 current_ai_->ai_addr, | 526 storage.addr, |
| 519 static_cast<int>(current_ai_->ai_addrlen))); | 527 storage.addr_len)); |
| 520 tcp_fastopen_connected_ = true; | 528 tcp_fastopen_connected_ = true; |
| 521 | 529 |
| 522 if (nwrite < 0) { | 530 if (nwrite < 0) { |
| 523 // Non-blocking mode is returning EINPROGRESS rather than EAGAIN. | 531 // Non-blocking mode is returning EINPROGRESS rather than EAGAIN. |
| 524 if (errno == EINPROGRESS) | 532 if (errno == EINPROGRESS) |
| 525 errno = EAGAIN; | 533 errno = EAGAIN; |
| 526 | 534 |
| 527 // Unlike "normal" nonblocking sockets, the data is already queued, | 535 // Unlike "normal" nonblocking sockets, the data is already queued, |
| 528 // so tell the app that we've consumed it. | 536 // so tell the app that we've consumed it. |
| 529 return buf_len; | 537 return buf_len; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 554 | 562 |
| 555 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) { | 563 void TCPClientSocketLibevent::LogConnectCompletion(int net_error) { |
| 556 if (net_error == OK) | 564 if (net_error == OK) |
| 557 UpdateConnectionTypeHistograms(CONNECTION_ANY); | 565 UpdateConnectionTypeHistograms(CONNECTION_ANY); |
| 558 | 566 |
| 559 if (net_error != OK) { | 567 if (net_error != OK) { |
| 560 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); | 568 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, net_error); |
| 561 return; | 569 return; |
| 562 } | 570 } |
| 563 | 571 |
| 564 struct sockaddr_storage source_address; | 572 SockaddrStorage storage; |
| 565 socklen_t addrlen = sizeof(source_address); | 573 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) { | 574 if (rv != 0) { |
| 569 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; | 575 PLOG(ERROR) << "getsockname() [rv: " << rv << "] error: "; |
| 570 NOTREACHED(); | 576 NOTREACHED(); |
| 571 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); | 577 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_CONNECT, rv); |
| 572 return; | 578 return; |
| 573 } | 579 } |
| 574 | 580 |
| 575 const std::string source_address_str = | 581 const std::string source_address_str = |
| 576 NetAddressToStringWithPort( | 582 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, | 583 net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, |
| 580 make_scoped_refptr(new NetLogStringParameter( | 584 make_scoped_refptr(new NetLogStringParameter( |
| 581 "source address", | 585 "source address", |
| 582 source_address_str))); | 586 source_address_str))); |
| 583 } | 587 } |
| 584 | 588 |
| 585 void TCPClientSocketLibevent::DoReadCallback(int rv) { | 589 void TCPClientSocketLibevent::DoReadCallback(int rv) { |
| 586 DCHECK_NE(rv, ERR_IO_PENDING); | 590 DCHECK_NE(rv, ERR_IO_PENDING); |
| 587 DCHECK(!read_callback_.is_null()); | 591 DCHECK(!read_callback_.is_null()); |
| 588 | 592 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 677 write_socket_watcher_.StopWatchingFileDescriptor(); | 681 write_socket_watcher_.StopWatchingFileDescriptor(); |
| 678 DoWriteCallback(result); | 682 DoWriteCallback(result); |
| 679 } | 683 } |
| 680 } | 684 } |
| 681 | 685 |
| 682 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { | 686 int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { |
| 683 DCHECK(CalledOnValidThread()); | 687 DCHECK(CalledOnValidThread()); |
| 684 DCHECK(address); | 688 DCHECK(address); |
| 685 if (!IsConnected()) | 689 if (!IsConnected()) |
| 686 return ERR_SOCKET_NOT_CONNECTED; | 690 return ERR_SOCKET_NOT_CONNECTED; |
| 687 *address = AddressList::CreateByCopyingFirstAddress(current_ai_); | 691 *address = AddressList(addresses_[current_address_index_]); |
| 688 return OK; | 692 return OK; |
| 689 } | 693 } |
| 690 | 694 |
| 691 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const { | 695 int TCPClientSocketLibevent::GetLocalAddress(IPEndPoint* address) const { |
| 692 DCHECK(CalledOnValidThread()); | 696 DCHECK(CalledOnValidThread()); |
| 693 DCHECK(address); | 697 DCHECK(address); |
| 694 if (!IsConnected()) | 698 if (!IsConnected()) |
| 695 return ERR_SOCKET_NOT_CONNECTED; | 699 return ERR_SOCKET_NOT_CONNECTED; |
| 696 | 700 |
| 697 struct sockaddr_storage addr_storage; | 701 SockaddrStorage storage; |
| 698 socklen_t addr_len = sizeof(addr_storage); | 702 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); | 703 return MapSystemError(errno); |
| 702 if (!address->FromSockAddr(addr, addr_len)) | 704 if (!address->FromSockAddr(storage.addr, storage.addr_len)) |
| 703 return ERR_FAILED; | 705 return ERR_FAILED; |
| 704 | 706 |
| 705 return OK; | 707 return OK; |
| 706 } | 708 } |
| 707 | 709 |
| 708 const BoundNetLog& TCPClientSocketLibevent::NetLog() const { | 710 const BoundNetLog& TCPClientSocketLibevent::NetLog() const { |
| 709 return net_log_; | 711 return net_log_; |
| 710 } | 712 } |
| 711 | 713 |
| 712 void TCPClientSocketLibevent::SetSubresourceSpeculation() { | 714 void TCPClientSocketLibevent::SetSubresourceSpeculation() { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 731 | 733 |
| 732 base::TimeDelta TCPClientSocketLibevent::GetConnectTimeMicros() const { | 734 base::TimeDelta TCPClientSocketLibevent::GetConnectTimeMicros() const { |
| 733 return connect_time_micros_; | 735 return connect_time_micros_; |
| 734 } | 736 } |
| 735 | 737 |
| 736 NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const { | 738 NextProto TCPClientSocketLibevent::GetNegotiatedProtocol() const { |
| 737 return kProtoUnknown; | 739 return kProtoUnknown; |
| 738 } | 740 } |
| 739 | 741 |
| 740 } // namespace net | 742 } // namespace net |
| OLD | NEW |