| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 | 298 |
| 299 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool( | 299 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool( |
| 300 HigherLayeredPool* higher_pool) { | 300 HigherLayeredPool* higher_pool) { |
| 301 CHECK(higher_pool); | 301 CHECK(higher_pool); |
| 302 CHECK(base::ContainsKey(higher_pools_, higher_pool)); | 302 CHECK(base::ContainsKey(higher_pools_, higher_pool)); |
| 303 higher_pools_.erase(higher_pool); | 303 higher_pools_.erase(higher_pool); |
| 304 } | 304 } |
| 305 | 305 |
| 306 int ClientSocketPoolBaseHelper::RequestSocket( | 306 int ClientSocketPoolBaseHelper::RequestSocket( |
| 307 const std::string& group_name, | 307 const std::string& group_name, |
| 308 std::unique_ptr<const Request> request) { | 308 std::unique_ptr<Request> request) { |
| 309 CHECK(!request->callback().is_null()); | 309 CHECK(!request->callback().is_null()); |
| 310 CHECK(request->handle()); | 310 CHECK(request->handle()); |
| 311 | 311 |
| 312 // Cleanup any timed-out idle sockets. | 312 // Cleanup any timed-out idle sockets. |
| 313 CleanupIdleSockets(false); | 313 CleanupIdleSockets(false); |
| 314 | 314 |
| 315 request->net_log().BeginEvent(NetLogEventType::SOCKET_POOL); | 315 request->net_log().BeginEvent(NetLogEventType::SOCKET_POOL); |
| 316 Group* group = GetOrCreateGroup(group_name); | 316 Group* group = GetOrCreateGroup(group_name); |
| 317 | 317 |
| 318 int rv = RequestSocketInternal(group_name, *request); | 318 int rv = RequestSocketInternal(group_name, *request); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 } | 555 } |
| 556 | 556 |
| 557 // static | 557 // static |
| 558 void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest( | 558 void ClientSocketPoolBaseHelper::LogBoundConnectJobToRequest( |
| 559 const NetLogSource& connect_job_source, | 559 const NetLogSource& connect_job_source, |
| 560 const Request& request) { | 560 const Request& request) { |
| 561 request.net_log().AddEvent(NetLogEventType::SOCKET_POOL_BOUND_TO_CONNECT_JOB, | 561 request.net_log().AddEvent(NetLogEventType::SOCKET_POOL_BOUND_TO_CONNECT_JOB, |
| 562 connect_job_source.ToEventParametersCallback()); | 562 connect_job_source.ToEventParametersCallback()); |
| 563 } | 563 } |
| 564 | 564 |
| 565 void ClientSocketPoolBaseHelper::SetPriority(const std::string& group_name, |
| 566 ClientSocketHandle* handle, |
| 567 RequestPriority priority) { |
| 568 GroupMap::iterator group_it = group_map_.find(group_name); |
| 569 if (group_it == group_map_.end()) { |
| 570 DCHECK(base::ContainsKey(pending_callback_map_, handle)); |
| 571 // The Request has already completed and been destroyed; nothing to |
| 572 // reprioritize. |
| 573 return; |
| 574 } |
| 575 |
| 576 group_it->second->SetPriority(handle, priority); |
| 577 } |
| 578 |
| 565 void ClientSocketPoolBaseHelper::CancelRequest( | 579 void ClientSocketPoolBaseHelper::CancelRequest( |
| 566 const std::string& group_name, ClientSocketHandle* handle) { | 580 const std::string& group_name, ClientSocketHandle* handle) { |
| 567 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); | 581 PendingCallbackMap::iterator callback_it = pending_callback_map_.find(handle); |
| 568 if (callback_it != pending_callback_map_.end()) { | 582 if (callback_it != pending_callback_map_.end()) { |
| 569 int result = callback_it->second.result; | 583 int result = callback_it->second.result; |
| 570 pending_callback_map_.erase(callback_it); | 584 pending_callback_map_.erase(callback_it); |
| 571 std::unique_ptr<StreamSocket> socket = handle->PassSocket(); | 585 std::unique_ptr<StreamSocket> socket = handle->PassSocket(); |
| 572 if (socket) { | 586 if (socket) { |
| 573 if (result != OK) | 587 if (result != OK) |
| 574 socket->Disconnect(); | 588 socket->Disconnect(); |
| 575 ReleaseSocket(handle->group_name(), std::move(socket), handle->id()); | 589 ReleaseSocket(handle->group_name(), std::move(socket), handle->id()); |
| 576 } | 590 } |
| 577 return; | 591 return; |
| 578 } | 592 } |
| 579 | 593 |
| 580 CHECK(base::ContainsKey(group_map_, group_name)); | 594 CHECK(base::ContainsKey(group_map_, group_name)); |
| 581 | 595 |
| 582 Group* group = GetOrCreateGroup(group_name); | 596 Group* group = GetOrCreateGroup(group_name); |
| 583 | 597 |
| 584 // Search pending_requests for matching handle. | 598 // Search pending_requests for matching handle. |
| 585 std::unique_ptr<const Request> request = | 599 std::unique_ptr<Request> request = group->FindAndRemovePendingRequest(handle); |
| 586 group->FindAndRemovePendingRequest(handle); | |
| 587 if (request) { | 600 if (request) { |
| 588 request->net_log().AddEvent(NetLogEventType::CANCELLED); | 601 request->net_log().AddEvent(NetLogEventType::CANCELLED); |
| 589 request->net_log().EndEvent(NetLogEventType::SOCKET_POOL); | 602 request->net_log().EndEvent(NetLogEventType::SOCKET_POOL); |
| 590 | 603 |
| 591 // We let the job run, unless we're at the socket limit and there is | 604 // We let the job run, unless we're at the socket limit and there is |
| 592 // not another request waiting on the job. | 605 // not another request waiting on the job. |
| 593 if (group->jobs().size() > group->pending_request_count() && | 606 if (group->jobs().size() > group->pending_request_count() && |
| 594 ReachedMaxSocketsLimit()) { | 607 ReachedMaxSocketsLimit()) { |
| 595 RemoveConnectJob(group->jobs().begin()->get(), group); | 608 RemoveConnectJob(group->jobs().begin()->get(), group); |
| 596 CheckForStalledSocketGroups(); | 609 CheckForStalledSocketGroups(); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 // accessed. | 973 // accessed. |
| 961 NetLogWithSource job_log = job->net_log(); | 974 NetLogWithSource job_log = job->net_log(); |
| 962 LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing(); | 975 LoadTimingInfo::ConnectTiming connect_timing = job->connect_timing(); |
| 963 | 976 |
| 964 // RemoveConnectJob(job, _) must be called by all branches below; | 977 // RemoveConnectJob(job, _) must be called by all branches below; |
| 965 // otherwise, |job| will be leaked. | 978 // otherwise, |job| will be leaked. |
| 966 | 979 |
| 967 if (result == OK) { | 980 if (result == OK) { |
| 968 DCHECK(socket.get()); | 981 DCHECK(socket.get()); |
| 969 RemoveConnectJob(job, group); | 982 RemoveConnectJob(job, group); |
| 970 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 983 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 971 if (request) { | 984 if (request) { |
| 972 LogBoundConnectJobToRequest(job_log.source(), *request); | 985 LogBoundConnectJobToRequest(job_log.source(), *request); |
| 973 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, | 986 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, |
| 974 connect_timing, request->handle(), base::TimeDelta(), group, | 987 connect_timing, request->handle(), base::TimeDelta(), group, |
| 975 request->net_log()); | 988 request->net_log()); |
| 976 request->net_log().EndEvent(NetLogEventType::SOCKET_POOL); | 989 request->net_log().EndEvent(NetLogEventType::SOCKET_POOL); |
| 977 InvokeUserCallbackLater(request->handle(), request->callback(), result); | 990 InvokeUserCallbackLater(request->handle(), request->callback(), result); |
| 978 } else { | 991 } else { |
| 979 AddIdleSocket(std::move(socket), group); | 992 AddIdleSocket(std::move(socket), group); |
| 980 OnAvailableSocketSlot(group_name, group); | 993 OnAvailableSocketSlot(group_name, group); |
| 981 CheckForStalledSocketGroups(); | 994 CheckForStalledSocketGroups(); |
| 982 } | 995 } |
| 983 } else { | 996 } else { |
| 984 // If we got a socket, it must contain error information so pass that | 997 // If we got a socket, it must contain error information so pass that |
| 985 // up so that the caller can retrieve it. | 998 // up so that the caller can retrieve it. |
| 986 bool handed_out_socket = false; | 999 bool handed_out_socket = false; |
| 987 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 1000 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 988 if (request) { | 1001 if (request) { |
| 989 LogBoundConnectJobToRequest(job_log.source(), *request); | 1002 LogBoundConnectJobToRequest(job_log.source(), *request); |
| 990 job->GetAdditionalErrorState(request->handle()); | 1003 job->GetAdditionalErrorState(request->handle()); |
| 991 RemoveConnectJob(job, group); | 1004 RemoveConnectJob(job, group); |
| 992 if (socket.get()) { | 1005 if (socket.get()) { |
| 993 handed_out_socket = true; | 1006 handed_out_socket = true; |
| 994 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, | 1007 HandOutSocket(std::move(socket), ClientSocketHandle::UNUSED, |
| 995 connect_timing, request->handle(), base::TimeDelta(), | 1008 connect_timing, request->handle(), base::TimeDelta(), |
| 996 group, request->net_log()); | 1009 group, request->net_log()); |
| 997 } | 1010 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 // If the group has no idle sockets, and can't make use of an additional slot, | 1059 // If the group has no idle sockets, and can't make use of an additional slot, |
| 1047 // either because it's at the limit or because it's at the socket per group | 1060 // either because it's at the limit or because it's at the socket per group |
| 1048 // limit, then there's nothing to do. | 1061 // limit, then there's nothing to do. |
| 1049 if (group->idle_sockets().empty() && | 1062 if (group->idle_sockets().empty() && |
| 1050 !group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { | 1063 !group->CanUseAdditionalSocketSlot(max_sockets_per_group_)) { |
| 1051 return; | 1064 return; |
| 1052 } | 1065 } |
| 1053 | 1066 |
| 1054 int rv = RequestSocketInternal(group_name, *next_request); | 1067 int rv = RequestSocketInternal(group_name, *next_request); |
| 1055 if (rv != ERR_IO_PENDING) { | 1068 if (rv != ERR_IO_PENDING) { |
| 1056 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 1069 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 1057 DCHECK(request); | 1070 DCHECK(request); |
| 1058 if (group->IsEmpty()) | 1071 if (group->IsEmpty()) |
| 1059 RemoveGroup(group_name); | 1072 RemoveGroup(group_name); |
| 1060 | 1073 |
| 1061 request->net_log().EndEventWithNetErrorCode(NetLogEventType::SOCKET_POOL, | 1074 request->net_log().EndEventWithNetErrorCode(NetLogEventType::SOCKET_POOL, |
| 1062 rv); | 1075 rv); |
| 1063 InvokeUserCallbackLater(request->handle(), request->callback(), rv); | 1076 InvokeUserCallbackLater(request->handle(), request->callback(), rv); |
| 1064 } | 1077 } |
| 1065 } | 1078 } |
| 1066 | 1079 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 } | 1146 } |
| 1134 } | 1147 } |
| 1135 DCHECK_EQ(0, connecting_socket_count_); | 1148 DCHECK_EQ(0, connecting_socket_count_); |
| 1136 } | 1149 } |
| 1137 | 1150 |
| 1138 void ClientSocketPoolBaseHelper::CancelAllRequestsWithError(int error) { | 1151 void ClientSocketPoolBaseHelper::CancelAllRequestsWithError(int error) { |
| 1139 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end();) { | 1152 for (GroupMap::iterator i = group_map_.begin(); i != group_map_.end();) { |
| 1140 Group* group = i->second; | 1153 Group* group = i->second; |
| 1141 | 1154 |
| 1142 while (true) { | 1155 while (true) { |
| 1143 std::unique_ptr<const Request> request = group->PopNextPendingRequest(); | 1156 std::unique_ptr<Request> request = group->PopNextPendingRequest(); |
| 1144 if (!request) | 1157 if (!request) |
| 1145 break; | 1158 break; |
| 1146 InvokeUserCallbackLater(request->handle(), request->callback(), error); | 1159 InvokeUserCallbackLater(request->handle(), request->callback(), error); |
| 1147 } | 1160 } |
| 1148 | 1161 |
| 1149 // Delete group if no longer needed. | 1162 // Delete group if no longer needed. |
| 1150 if (group->IsEmpty()) { | 1163 if (group->IsEmpty()) { |
| 1151 // RemoveGroup() will call .erase() which will invalidate the iterator, | 1164 // RemoveGroup() will call .erase() which will invalidate the iterator, |
| 1152 // but i will already have been incremented to a valid iterator before | 1165 // but i will already have been incremented to a valid iterator before |
| 1153 // RemoveGroup() is called. | 1166 // RemoveGroup() is called. |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); | 1389 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); |
| 1377 !pointer.is_null() && i < jobs_.size(); | 1390 !pointer.is_null() && i < jobs_.size(); |
| 1378 pointer = pending_requests_.GetNextTowardsLastMin(pointer), ++i) { | 1391 pointer = pending_requests_.GetNextTowardsLastMin(pointer), ++i) { |
| 1379 if (pointer.value()->handle() == handle) | 1392 if (pointer.value()->handle() == handle) |
| 1380 return true; | 1393 return true; |
| 1381 } | 1394 } |
| 1382 return false; | 1395 return false; |
| 1383 } | 1396 } |
| 1384 | 1397 |
| 1385 void ClientSocketPoolBaseHelper::Group::InsertPendingRequest( | 1398 void ClientSocketPoolBaseHelper::Group::InsertPendingRequest( |
| 1386 std::unique_ptr<const Request> request) { | 1399 std::unique_ptr<Request> request) { |
| 1387 // This value must be cached before we release |request|. | 1400 // This value must be cached before we release |request|. |
| 1388 RequestPriority priority = request->priority(); | 1401 RequestPriority priority = request->priority(); |
| 1389 if (request->respect_limits() == ClientSocketPool::RespectLimits::DISABLED) { | 1402 if (request->respect_limits() == ClientSocketPool::RespectLimits::DISABLED) { |
| 1390 // Put requests with RespectLimits::DISABLED (which should have | 1403 // Put requests with RespectLimits::DISABLED (which should have |
| 1391 // priority == MAXIMUM_PRIORITY) ahead of other requests with | 1404 // priority == MAXIMUM_PRIORITY) ahead of other requests with |
| 1392 // MAXIMUM_PRIORITY. | 1405 // MAXIMUM_PRIORITY. |
| 1393 DCHECK_EQ(priority, MAXIMUM_PRIORITY); | 1406 DCHECK_EQ(priority, MAXIMUM_PRIORITY); |
| 1394 pending_requests_.InsertAtFront(request.release(), priority); | 1407 pending_requests_.InsertAtFront(request.release(), priority); |
| 1395 } else { | 1408 } else { |
| 1396 pending_requests_.Insert(request.release(), priority); | 1409 pending_requests_.Insert(request.release(), priority); |
| 1397 } | 1410 } |
| 1398 } | 1411 } |
| 1399 | 1412 |
| 1400 std::unique_ptr<const ClientSocketPoolBaseHelper::Request> | 1413 std::unique_ptr<ClientSocketPoolBaseHelper::Request> |
| 1401 ClientSocketPoolBaseHelper::Group::PopNextPendingRequest() { | 1414 ClientSocketPoolBaseHelper::Group::PopNextPendingRequest() { |
| 1402 if (pending_requests_.empty()) | 1415 if (pending_requests_.empty()) |
| 1403 return std::unique_ptr<const ClientSocketPoolBaseHelper::Request>(); | 1416 return std::unique_ptr<ClientSocketPoolBaseHelper::Request>(); |
| 1404 return RemovePendingRequest(pending_requests_.FirstMax()); | 1417 return RemovePendingRequest(pending_requests_.FirstMax()); |
| 1405 } | 1418 } |
| 1406 | 1419 |
| 1407 std::unique_ptr<const ClientSocketPoolBaseHelper::Request> | 1420 std::unique_ptr<ClientSocketPoolBaseHelper::Request> |
| 1408 ClientSocketPoolBaseHelper::Group::FindAndRemovePendingRequest( | 1421 ClientSocketPoolBaseHelper::Group::FindAndRemovePendingRequest( |
| 1409 ClientSocketHandle* handle) { | 1422 ClientSocketHandle* handle) { |
| 1410 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); | 1423 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); |
| 1411 !pointer.is_null(); | 1424 !pointer.is_null(); |
| 1412 pointer = pending_requests_.GetNextTowardsLastMin(pointer)) { | 1425 pointer = pending_requests_.GetNextTowardsLastMin(pointer)) { |
| 1413 if (pointer.value()->handle() == handle) { | 1426 if (pointer.value()->handle() == handle) { |
| 1414 std::unique_ptr<const Request> request = RemovePendingRequest(pointer); | 1427 DCHECK_EQ(static_cast<RequestPriority>(pointer.priority()), |
| 1428 pointer.value()->priority()); |
| 1429 std::unique_ptr<Request> request = RemovePendingRequest(pointer); |
| 1415 return request; | 1430 return request; |
| 1416 } | 1431 } |
| 1417 } | 1432 } |
| 1418 return std::unique_ptr<const ClientSocketPoolBaseHelper::Request>(); | 1433 return std::unique_ptr<ClientSocketPoolBaseHelper::Request>(); |
| 1419 } | 1434 } |
| 1420 | 1435 |
| 1421 std::unique_ptr<const ClientSocketPoolBaseHelper::Request> | 1436 void ClientSocketPoolBaseHelper::Group::SetPriority(ClientSocketHandle* handle, |
| 1437 RequestPriority priority) { |
| 1438 for (RequestQueue::Pointer pointer = pending_requests_.FirstMax(); |
| 1439 !pointer.is_null(); |
| 1440 pointer = pending_requests_.GetNextTowardsLastMin(pointer)) { |
| 1441 if (pointer.value()->handle() == handle) { |
| 1442 if (pointer.value()->priority() == priority) |
| 1443 return; |
| 1444 |
| 1445 std::unique_ptr<Request> request = RemovePendingRequest(pointer); |
| 1446 |
| 1447 // Requests that ignore limits much be created and remain at the highest |
| 1448 // priority, and should not be reprioritized. |
| 1449 DCHECK_EQ(request->respect_limits(), |
| 1450 ClientSocketPool::RespectLimits::ENABLED); |
| 1451 |
| 1452 request->set_priority(priority); |
| 1453 InsertPendingRequest(std::move(request)); |
| 1454 return; |
| 1455 } |
| 1456 } |
| 1457 |
| 1458 // This function must be called with a valid ClientSocketHandle. |
| 1459 NOTREACHED(); |
| 1460 } |
| 1461 |
| 1462 std::unique_ptr<ClientSocketPoolBaseHelper::Request> |
| 1422 ClientSocketPoolBaseHelper::Group::RemovePendingRequest( | 1463 ClientSocketPoolBaseHelper::Group::RemovePendingRequest( |
| 1423 const RequestQueue::Pointer& pointer) { | 1464 const RequestQueue::Pointer& pointer) { |
| 1424 // TODO(eroman): Temporary for debugging http://crbug.com/467797. | 1465 // TODO(eroman): Temporary for debugging http://crbug.com/467797. |
| 1425 CHECK(!pointer.is_null()); | 1466 CHECK(!pointer.is_null()); |
| 1426 std::unique_ptr<const Request> request(pointer.value()); | 1467 std::unique_ptr<Request> request(pointer.value()); |
| 1427 pending_requests_.Erase(pointer); | 1468 pending_requests_.Erase(pointer); |
| 1428 // If there are no more requests, kill the backup timer. | 1469 // If there are no more requests, kill the backup timer. |
| 1429 if (pending_requests_.empty()) | 1470 if (pending_requests_.empty()) |
| 1430 backup_job_timer_.Stop(); | 1471 backup_job_timer_.Stop(); |
| 1431 request->CrashIfInvalid(); | 1472 request->CrashIfInvalid(); |
| 1432 return request; | 1473 return request; |
| 1433 } | 1474 } |
| 1434 | 1475 |
| 1435 } // namespace internal | 1476 } // namespace internal |
| 1436 | 1477 |
| 1437 } // namespace net | 1478 } // namespace net |
| OLD | NEW |