| 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/client_socket_pool_base.h" | 5 #include "net/socket/client_socket_pool_base.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 LogConnectCompletion(rv); | 118 LogConnectCompletion(rv); |
| 119 delegate->OnConnectJobComplete(rv, this); | 119 delegate->OnConnectJobComplete(rv, this); |
| 120 } | 120 } |
| 121 | 121 |
| 122 void ConnectJob::ResetTimer(base::TimeDelta remaining_time) { | 122 void ConnectJob::ResetTimer(base::TimeDelta remaining_time) { |
| 123 timer_.Stop(); | 123 timer_.Stop(); |
| 124 timer_.Start(FROM_HERE, remaining_time, this, &ConnectJob::OnTimeout); | 124 timer_.Start(FROM_HERE, remaining_time, this, &ConnectJob::OnTimeout); |
| 125 } | 125 } |
| 126 | 126 |
| 127 void ConnectJob::LogConnectStart() { | 127 void ConnectJob::LogConnectStart() { |
| 128 connect_timing_.connect_start = base::TimeTicks::Now(); |
| 128 net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT, | 129 net_log().BeginEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT, |
| 129 NetLog::StringCallback("group_name", &group_name_)); | 130 NetLog::StringCallback("group_name", &group_name_)); |
| 130 } | 131 } |
| 131 | 132 |
| 132 void ConnectJob::LogConnectCompletion(int net_error) { | 133 void ConnectJob::LogConnectCompletion(int net_error) { |
| 134 connect_timing_.connect_end = base::TimeTicks::Now(); |
| 133 net_log().EndEventWithNetErrorCode( | 135 net_log().EndEventWithNetErrorCode( |
| 134 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT, net_error); | 136 NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_CONNECT, net_error); |
| 135 } | 137 } |
| 136 | 138 |
| 137 void ConnectJob::OnTimeout() { | 139 void ConnectJob::OnTimeout() { |
| 138 // Make sure the socket is NULL before calling into |delegate|. | 140 // Make sure the socket is NULL before calling into |delegate|. |
| 139 set_socket(NULL); | 141 set_socket(NULL); |
| 140 | 142 |
| 141 net_log_.AddEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_TIMED_OUT); | 143 net_log_.AddEvent(NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_TIMED_OUT); |
| 142 | 144 |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 // We couldn't find a socket to reuse, and there's space to allocate one, | 378 // We couldn't find a socket to reuse, and there's space to allocate one, |
| 377 // so allocate and connect a new one. | 379 // so allocate and connect a new one. |
| 378 scoped_ptr<ConnectJob> connect_job( | 380 scoped_ptr<ConnectJob> connect_job( |
| 379 connect_job_factory_->NewConnectJob(group_name, *request, this)); | 381 connect_job_factory_->NewConnectJob(group_name, *request, this)); |
| 380 | 382 |
| 381 int rv = connect_job->Connect(); | 383 int rv = connect_job->Connect(); |
| 382 if (rv == OK) { | 384 if (rv == OK) { |
| 383 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); | 385 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); |
| 384 if (!preconnecting) { | 386 if (!preconnecting) { |
| 385 HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */, | 387 HandOutSocket(connect_job->ReleaseSocket(), false /* not reused */, |
| 386 handle, base::TimeDelta(), group, request->net_log()); | 388 connect_job->connect_timing(), handle, base::TimeDelta(), |
| 389 group, request->net_log()); |
| 387 } else { | 390 } else { |
| 388 AddIdleSocket(connect_job->ReleaseSocket(), group); | 391 AddIdleSocket(connect_job->ReleaseSocket(), group); |
| 389 } | 392 } |
| 390 } else if (rv == ERR_IO_PENDING) { | 393 } else if (rv == ERR_IO_PENDING) { |
| 391 // If we don't have any sockets in this group, set a timer for potentially | 394 // If we don't have any sockets in this group, set a timer for potentially |
| 392 // creating a new one. If the SYN is lost, this backup socket may complete | 395 // creating a new one. If the SYN is lost, this backup socket may complete |
| 393 // before the slow socket, improving end user latency. | 396 // before the slow socket, improving end user latency. |
| 394 if (connect_backup_jobs_enabled_ && | 397 if (connect_backup_jobs_enabled_ && |
| 395 group->IsEmpty() && !group->HasBackupJob()) { | 398 group->IsEmpty() && !group->HasBackupJob()) { |
| 396 group->StartBackupSocketTimer(group_name, this); | 399 group->StartBackupSocketTimer(group_name, this); |
| 397 } | 400 } |
| 398 | 401 |
| 399 connecting_socket_count_++; | 402 connecting_socket_count_++; |
| 400 | 403 |
| 401 group->AddJob(connect_job.release(), preconnecting); | 404 group->AddJob(connect_job.release(), preconnecting); |
| 402 } else { | 405 } else { |
| 403 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); | 406 LogBoundConnectJobToRequest(connect_job->net_log().source(), request); |
| 404 StreamSocket* error_socket = NULL; | 407 StreamSocket* error_socket = NULL; |
| 405 if (!preconnecting) { | 408 if (!preconnecting) { |
| 406 DCHECK(handle); | 409 DCHECK(handle); |
| 407 connect_job->GetAdditionalErrorState(handle); | 410 connect_job->GetAdditionalErrorState(handle); |
| 408 error_socket = connect_job->ReleaseSocket(); | 411 error_socket = connect_job->ReleaseSocket(); |
| 409 } | 412 } |
| 410 if (error_socket) { | 413 if (error_socket) { |
| 411 HandOutSocket(error_socket, false /* not reused */, handle, | 414 HandOutSocket(error_socket, false /* not reused */, |
| 412 base::TimeDelta(), group, request->net_log()); | 415 connect_job->connect_timing(), handle, base::TimeDelta(), |
| 416 group, request->net_log()); |
| 413 } else if (group->IsEmpty()) { | 417 } else if (group->IsEmpty()) { |
| 414 RemoveGroup(group_name); | 418 RemoveGroup(group_name); |
| 415 } | 419 } |
| 416 } | 420 } |
| 417 | 421 |
| 418 return rv; | 422 return rv; |
| 419 } | 423 } |
| 420 | 424 |
| 421 bool ClientSocketPoolBaseHelper::AssignIdleSocketToRequest( | 425 bool ClientSocketPoolBaseHelper::AssignIdleSocketToRequest( |
| 422 const Request* request, Group* group) { | 426 const Request* request, Group* group) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 | 472 |
| 469 if (idle_socket_it != idle_sockets->end()) { | 473 if (idle_socket_it != idle_sockets->end()) { |
| 470 DecrementIdleCount(); | 474 DecrementIdleCount(); |
| 471 base::TimeDelta idle_time = | 475 base::TimeDelta idle_time = |
| 472 base::TimeTicks::Now() - idle_socket_it->start_time; | 476 base::TimeTicks::Now() - idle_socket_it->start_time; |
| 473 IdleSocket idle_socket = *idle_socket_it; | 477 IdleSocket idle_socket = *idle_socket_it; |
| 474 idle_sockets->erase(idle_socket_it); | 478 idle_sockets->erase(idle_socket_it); |
| 475 HandOutSocket( | 479 HandOutSocket( |
| 476 idle_socket.socket, | 480 idle_socket.socket, |
| 477 idle_socket.socket->WasEverUsed(), | 481 idle_socket.socket->WasEverUsed(), |
| 482 ConnectTiming(), |
| 478 request->handle(), | 483 request->handle(), |
| 479 idle_time, | 484 idle_time, |
| 480 group, | 485 group, |
| 481 request->net_log()); | 486 request->net_log()); |
| 482 return true; | 487 return true; |
| 483 } | 488 } |
| 484 | 489 |
| 485 return false; | 490 return false; |
| 486 } | 491 } |
| 487 | 492 |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 void ClientSocketPoolBaseHelper::OnConnectJobComplete( | 853 void ClientSocketPoolBaseHelper::OnConnectJobComplete( |
| 849 int result, ConnectJob* job) { | 854 int result, ConnectJob* job) { |
| 850 DCHECK_NE(ERR_IO_PENDING, result); | 855 DCHECK_NE(ERR_IO_PENDING, result); |
| 851 const std::string group_name = job->group_name(); | 856 const std::string group_name = job->group_name(); |
| 852 GroupMap::iterator group_it = group_map_.find(group_name); | 857 GroupMap::iterator group_it = group_map_.find(group_name); |
| 853 CHECK(group_it != group_map_.end()); | 858 CHECK(group_it != group_map_.end()); |
| 854 Group* group = group_it->second; | 859 Group* group = group_it->second; |
| 855 | 860 |
| 856 scoped_ptr<StreamSocket> socket(job->ReleaseSocket()); | 861 scoped_ptr<StreamSocket> socket(job->ReleaseSocket()); |
| 857 | 862 |
| 863 // Copies of these are needed because |job| may be deleted before they are |
| 864 // accessed. |
| 858 BoundNetLog job_log = job->net_log(); | 865 BoundNetLog job_log = job->net_log(); |
| 866 ConnectTiming connect_timing = job->connect_timing(); |
| 859 | 867 |
| 860 if (result == OK) { | 868 if (result == OK) { |
| 861 DCHECK(socket.get()); | 869 DCHECK(socket.get()); |
| 862 RemoveConnectJob(job, group); | 870 RemoveConnectJob(job, group); |
| 863 if (!group->pending_requests().empty()) { | 871 if (!group->pending_requests().empty()) { |
| 864 scoped_ptr<const Request> r(RemoveRequestFromQueue( | 872 scoped_ptr<const Request> r(RemoveRequestFromQueue( |
| 865 group->mutable_pending_requests()->begin(), group)); | 873 group->mutable_pending_requests()->begin(), group)); |
| 866 LogBoundConnectJobToRequest(job_log.source(), r.get()); | 874 LogBoundConnectJobToRequest(job_log.source(), r.get()); |
| 867 HandOutSocket( | 875 HandOutSocket( |
| 868 socket.release(), false /* unused socket */, r->handle(), | 876 socket.release(), false /* unused socket */, connect_timing, |
| 869 base::TimeDelta(), group, r->net_log()); | 877 r->handle(), base::TimeDelta(), group, r->net_log()); |
| 870 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); | 878 r->net_log().EndEvent(NetLog::TYPE_SOCKET_POOL); |
| 871 InvokeUserCallbackLater(r->handle(), r->callback(), result); | 879 InvokeUserCallbackLater(r->handle(), r->callback(), result); |
| 872 } else { | 880 } else { |
| 873 AddIdleSocket(socket.release(), group); | 881 AddIdleSocket(socket.release(), group); |
| 874 OnAvailableSocketSlot(group_name, group); | 882 OnAvailableSocketSlot(group_name, group); |
| 875 CheckForStalledSocketGroups(); | 883 CheckForStalledSocketGroups(); |
| 876 } | 884 } |
| 877 } else { | 885 } else { |
| 878 // If we got a socket, it must contain error information so pass that | 886 // If we got a socket, it must contain error information so pass that |
| 879 // up so that the caller can retrieve it. | 887 // up so that the caller can retrieve it. |
| 880 bool handed_out_socket = false; | 888 bool handed_out_socket = false; |
| 881 if (!group->pending_requests().empty()) { | 889 if (!group->pending_requests().empty()) { |
| 882 scoped_ptr<const Request> r(RemoveRequestFromQueue( | 890 scoped_ptr<const Request> r(RemoveRequestFromQueue( |
| 883 group->mutable_pending_requests()->begin(), group)); | 891 group->mutable_pending_requests()->begin(), group)); |
| 884 LogBoundConnectJobToRequest(job_log.source(), r.get()); | 892 LogBoundConnectJobToRequest(job_log.source(), r.get()); |
| 885 job->GetAdditionalErrorState(r->handle()); | 893 job->GetAdditionalErrorState(r->handle()); |
| 886 RemoveConnectJob(job, group); | 894 RemoveConnectJob(job, group); |
| 887 if (socket.get()) { | 895 if (socket.get()) { |
| 888 handed_out_socket = true; | 896 handed_out_socket = true; |
| 889 HandOutSocket(socket.release(), false /* unused socket */, r->handle(), | 897 HandOutSocket(socket.release(), false /* unused socket */, |
| 890 base::TimeDelta(), group, r->net_log()); | 898 connect_timing, r->handle(), base::TimeDelta(), group, |
| 899 r->net_log()); |
| 891 } | 900 } |
| 892 r->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, | 901 r->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, result); |
| 893 result); | |
| 894 InvokeUserCallbackLater(r->handle(), r->callback(), result); | 902 InvokeUserCallbackLater(r->handle(), r->callback(), result); |
| 895 } else { | 903 } else { |
| 896 RemoveConnectJob(job, group); | 904 RemoveConnectJob(job, group); |
| 897 } | 905 } |
| 898 if (!handed_out_socket) { | 906 if (!handed_out_socket) { |
| 899 OnAvailableSocketSlot(group_name, group); | 907 OnAvailableSocketSlot(group_name, group); |
| 900 CheckForStalledSocketGroups(); | 908 CheckForStalledSocketGroups(); |
| 901 } | 909 } |
| 902 } | 910 } |
| 903 } | 911 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 RemoveGroup(group_name); | 978 RemoveGroup(group_name); |
| 971 | 979 |
| 972 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); | 980 request->net_log().EndEventWithNetErrorCode(NetLog::TYPE_SOCKET_POOL, rv); |
| 973 InvokeUserCallbackLater(request->handle(), request->callback(), rv); | 981 InvokeUserCallbackLater(request->handle(), request->callback(), rv); |
| 974 } | 982 } |
| 975 } | 983 } |
| 976 | 984 |
| 977 void ClientSocketPoolBaseHelper::HandOutSocket( | 985 void ClientSocketPoolBaseHelper::HandOutSocket( |
| 978 StreamSocket* socket, | 986 StreamSocket* socket, |
| 979 bool reused, | 987 bool reused, |
| 988 const ConnectTiming& connect_timing, |
| 980 ClientSocketHandle* handle, | 989 ClientSocketHandle* handle, |
| 981 base::TimeDelta idle_time, | 990 base::TimeDelta idle_time, |
| 982 Group* group, | 991 Group* group, |
| 983 const BoundNetLog& net_log) { | 992 const BoundNetLog& net_log) { |
| 984 DCHECK(socket); | 993 DCHECK(socket); |
| 985 handle->set_socket(socket); | 994 handle->set_socket(socket); |
| 986 handle->set_is_reused(reused); | 995 handle->set_is_reused(reused); |
| 987 handle->set_idle_time(idle_time); | 996 handle->set_idle_time(idle_time); |
| 988 handle->set_pool_id(pool_generation_number_); | 997 handle->set_pool_id(pool_generation_number_); |
| 998 handle->set_connect_timing(connect_timing); |
| 989 | 999 |
| 990 if (reused) { | 1000 if (reused) { |
| 991 net_log.AddEvent( | 1001 net_log.AddEvent( |
| 992 NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, | 1002 NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET, |
| 993 NetLog::IntegerCallback( | 1003 NetLog::IntegerCallback( |
| 994 "idle_ms", static_cast<int>(idle_time.InMilliseconds()))); | 1004 "idle_ms", static_cast<int>(idle_time.InMilliseconds()))); |
| 995 } | 1005 } |
| 996 | 1006 |
| 997 net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, | 1007 net_log.AddEvent(NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET, |
| 998 socket->NetLog().source().ToEventParametersCallback()); | 1008 socket->NetLog().source().ToEventParametersCallback()); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1229 STLDeleteElements(&jobs_); | 1239 STLDeleteElements(&jobs_); |
| 1230 unassigned_job_count_ = 0; | 1240 unassigned_job_count_ = 0; |
| 1231 | 1241 |
| 1232 // Cancel pending backup job. | 1242 // Cancel pending backup job. |
| 1233 weak_factory_.InvalidateWeakPtrs(); | 1243 weak_factory_.InvalidateWeakPtrs(); |
| 1234 } | 1244 } |
| 1235 | 1245 |
| 1236 } // namespace internal | 1246 } // namespace internal |
| 1237 | 1247 |
| 1238 } // namespace net | 1248 } // namespace net |
| OLD | NEW |