diff options
Diffstat (limited to 'net/websockets')
-rw-r--r-- | net/websockets/websocket_throttle.cc | 16 | ||||
-rw-r--r-- | net/websockets/websocket_throttle_unittest.cc | 25 |
2 files changed, 41 insertions, 0 deletions
diff --git a/net/websockets/websocket_throttle.cc b/net/websockets/websocket_throttle.cc index e2e98c3..9e33cad 100644 --- a/net/websockets/websocket_throttle.cc +++ b/net/websockets/websocket_throttle.cc @@ -6,6 +6,7 @@ #include <string> +#include "base/hash_tables.h" #include "base/message_loop.h" #include "base/ref_counted.h" #include "base/singleton.h" @@ -53,10 +54,17 @@ WebSocketThrottle::~WebSocketThrottle() { void WebSocketThrottle::PutInQueue(WebSocketJob* job) { queue_.push_back(job); const AddressList& address_list = job->address_list(); + base::hash_set<std::string> address_set; for (const struct addrinfo* addrinfo = address_list.head(); addrinfo != NULL; addrinfo = addrinfo->ai_next) { std::string addrkey = AddrinfoToHashkey(addrinfo); + + // If |addrkey| is already processed, don't do it again. + if (address_set.find(addrkey) != address_set.end()) + continue; + address_set.insert(addrkey); + ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); if (iter == addr_map_.end()) { ConnectingQueue* queue = new ConnectingQueue(); @@ -65,6 +73,7 @@ void WebSocketThrottle::PutInQueue(WebSocketJob* job) { } else { iter->second->push_back(job); job->SetWaiting(); + DLOG(INFO) << "Waiting on " << addrkey; } } } @@ -83,12 +92,19 @@ void WebSocketThrottle::RemoveFromQueue(WebSocketJob* job) { if (!in_queue) return; const AddressList& address_list = job->address_list(); + base::hash_set<std::string> address_set; for (const struct addrinfo* addrinfo = address_list.head(); addrinfo != NULL; addrinfo = addrinfo->ai_next) { std::string addrkey = AddrinfoToHashkey(addrinfo); + // If |addrkey| is already processed, don't do it again. + if (address_set.find(addrkey) != address_set.end()) + continue; + address_set.insert(addrkey); + ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); DCHECK(iter != addr_map_.end()); + ConnectingQueue* queue = iter->second; // Job may not be front of queue when job is closed early while waiting. for (ConnectingQueue::iterator iter = queue->begin(); diff --git a/net/websockets/websocket_throttle_unittest.cc b/net/websockets/websocket_throttle_unittest.cc index 91d588f..6c0dfbb 100644 --- a/net/websockets/websocket_throttle_unittest.cc +++ b/net/websockets/websocket_throttle_unittest.cc @@ -279,4 +279,29 @@ TEST_F(WebSocketThrottleTest, Throttle) { MessageLoopForIO::current()->RunAllPending(); } +TEST_F(WebSocketThrottleTest, NoThrottleForDuplicateAddress) { + DummySocketStreamDelegate delegate; + + // For localhost: 127.0.0.1, 127.0.0.1 + struct addrinfo* addr = AddAddr(127, 0, 0, 1, NULL); + addr = AddAddr(127, 0, 0, 1, addr); + scoped_refptr<WebSocketJob> w1 = new WebSocketJob(&delegate); + scoped_refptr<SocketStream> s1 = + new SocketStream(GURL("ws://localhost/"), w1.get()); + w1->InitSocketStream(s1.get()); + WebSocketThrottleTest::MockSocketStreamConnect(s1, addr); + DeleteAddrInfo(addr); + + DLOG(INFO) << "socket1"; + TestCompletionCallback callback_s1; + // Trying to open connection to localhost will start without wait. + EXPECT_EQ(OK, w1->OnStartOpenConnection(s1, &callback_s1)); + + DLOG(INFO) << "socket1 close"; + w1->OnClose(s1.get()); + s1->DetachDelegate(); + DLOG(INFO) << "Done"; + MessageLoopForIO::current()->RunAllPending(); +} + } |