| OLD | NEW |
| 1 // Copyright (c) 2011 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/websockets/websocket_throttle.h" | 5 #include "net/websockets/websocket_throttle.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/hash_tables.h" | 9 #include "base/hash_tables.h" |
| 10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
| 11 #include "base/memory/singleton.h" | 11 #include "base/memory/singleton.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
| 16 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
| 17 #include "net/base/sys_addrinfo.h" | |
| 18 #include "net/socket_stream/socket_stream.h" | 17 #include "net/socket_stream/socket_stream.h" |
| 19 #include "net/websockets/websocket_job.h" | 18 #include "net/websockets/websocket_job.h" |
| 20 | 19 |
| 21 namespace net { | 20 namespace net { |
| 22 | 21 |
| 23 static std::string AddrinfoToHashkey(const struct addrinfo* addrinfo) { | 22 static std::string IPEndPointToHashkey(const IPEndPoint& endpoint) { |
| 24 switch (addrinfo->ai_family) { | 23 return base::StringPrintf("%d:%s", |
| 25 case AF_INET: { | 24 endpoint.GetFamily(), |
| 26 const struct sockaddr_in* const addr = | 25 base::HexEncode(&endpoint.address()[0], |
| 27 reinterpret_cast<const sockaddr_in*>(addrinfo->ai_addr); | 26 endpoint.address().size()).c_str()); |
| 28 return base::StringPrintf("%d:%s", | |
| 29 addrinfo->ai_family, | |
| 30 base::HexEncode(&addr->sin_addr, 4).c_str()); | |
| 31 } | |
| 32 case AF_INET6: { | |
| 33 const struct sockaddr_in6* const addr6 = | |
| 34 reinterpret_cast<const sockaddr_in6*>(addrinfo->ai_addr); | |
| 35 return base::StringPrintf( | |
| 36 "%d:%s", | |
| 37 addrinfo->ai_family, | |
| 38 base::HexEncode(&addr6->sin6_addr, | |
| 39 sizeof(addr6->sin6_addr)).c_str()); | |
| 40 } | |
| 41 default: | |
| 42 return base::StringPrintf("%d:%s", | |
| 43 addrinfo->ai_family, | |
| 44 base::HexEncode(addrinfo->ai_addr, | |
| 45 addrinfo->ai_addrlen).c_str()); | |
| 46 } | |
| 47 } | 27 } |
| 48 | 28 |
| 49 WebSocketThrottle::WebSocketThrottle() { | 29 WebSocketThrottle::WebSocketThrottle() { |
| 50 } | 30 } |
| 51 | 31 |
| 52 WebSocketThrottle::~WebSocketThrottle() { | 32 WebSocketThrottle::~WebSocketThrottle() { |
| 53 DCHECK(queue_.empty()); | 33 DCHECK(queue_.empty()); |
| 54 DCHECK(addr_map_.empty()); | 34 DCHECK(addr_map_.empty()); |
| 55 } | 35 } |
| 56 | 36 |
| 57 // static | 37 // static |
| 58 WebSocketThrottle* WebSocketThrottle::GetInstance() { | 38 WebSocketThrottle* WebSocketThrottle::GetInstance() { |
| 59 return Singleton<WebSocketThrottle>::get(); | 39 return Singleton<WebSocketThrottle>::get(); |
| 60 } | 40 } |
| 61 | 41 |
| 62 void WebSocketThrottle::PutInQueue(WebSocketJob* job) { | 42 void WebSocketThrottle::PutInQueue(WebSocketJob* job) { |
| 63 queue_.push_back(job); | 43 queue_.push_back(job); |
| 64 const AddressList& address_list = job->address_list(); | 44 const AddressList& address_list = job->address_list(); |
| 65 base::hash_set<std::string> address_set; | 45 base::hash_set<std::string> address_set; |
| 66 for (const struct addrinfo* addrinfo = address_list.head(); | 46 for (AddressList::const_iterator addr_iter = address_list.begin(); |
| 67 addrinfo != NULL; | 47 addr_iter != address_list.end(); |
| 68 addrinfo = addrinfo->ai_next) { | 48 ++addr_iter) { |
| 69 std::string addrkey = AddrinfoToHashkey(addrinfo); | 49 std::string addrkey = IPEndPointToHashkey(*addr_iter); |
| 70 | 50 |
| 71 // If |addrkey| is already processed, don't do it again. | 51 // If |addrkey| is already processed, don't do it again. |
| 72 if (address_set.find(addrkey) != address_set.end()) | 52 if (address_set.find(addrkey) != address_set.end()) |
| 73 continue; | 53 continue; |
| 74 address_set.insert(addrkey); | 54 address_set.insert(addrkey); |
| 75 | 55 |
| 76 ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); | 56 ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); |
| 77 if (iter == addr_map_.end()) { | 57 if (iter == addr_map_.end()) { |
| 78 ConnectingQueue* queue = new ConnectingQueue(); | 58 ConnectingQueue* queue = new ConnectingQueue(); |
| 79 queue->push_back(job); | 59 queue->push_back(job); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 94 if (*iter == job) { | 74 if (*iter == job) { |
| 95 queue_.erase(iter); | 75 queue_.erase(iter); |
| 96 in_queue = true; | 76 in_queue = true; |
| 97 break; | 77 break; |
| 98 } | 78 } |
| 99 } | 79 } |
| 100 if (!in_queue) | 80 if (!in_queue) |
| 101 return; | 81 return; |
| 102 const AddressList& address_list = job->address_list(); | 82 const AddressList& address_list = job->address_list(); |
| 103 base::hash_set<std::string> address_set; | 83 base::hash_set<std::string> address_set; |
| 104 for (const struct addrinfo* addrinfo = address_list.head(); | 84 for (AddressList::const_iterator addr_iter = address_list.begin(); |
| 105 addrinfo != NULL; | 85 addr_iter != address_list.end(); |
| 106 addrinfo = addrinfo->ai_next) { | 86 ++addr_iter) { |
| 107 std::string addrkey = AddrinfoToHashkey(addrinfo); | 87 std::string addrkey = IPEndPointToHashkey(*addr_iter); |
| 108 // If |addrkey| is already processed, don't do it again. | 88 // If |addrkey| is already processed, don't do it again. |
| 109 if (address_set.find(addrkey) != address_set.end()) | 89 if (address_set.find(addrkey) != address_set.end()) |
| 110 continue; | 90 continue; |
| 111 address_set.insert(addrkey); | 91 address_set.insert(addrkey); |
| 112 | 92 |
| 113 ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); | 93 ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); |
| 114 DCHECK(iter != addr_map_.end()); | 94 DCHECK(iter != addr_map_.end()); |
| 115 | 95 |
| 116 ConnectingQueue* queue = iter->second; | 96 ConnectingQueue* queue = iter->second; |
| 117 // Job may not be front of queue when job is closed early while waiting. | 97 // Job may not be front of queue when job is closed early while waiting. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 133 void WebSocketThrottle::WakeupSocketIfNecessary() { | 113 void WebSocketThrottle::WakeupSocketIfNecessary() { |
| 134 for (ConnectingQueue::iterator iter = queue_.begin(); | 114 for (ConnectingQueue::iterator iter = queue_.begin(); |
| 135 iter != queue_.end(); | 115 iter != queue_.end(); |
| 136 ++iter) { | 116 ++iter) { |
| 137 WebSocketJob* job = *iter; | 117 WebSocketJob* job = *iter; |
| 138 if (!job->IsWaiting()) | 118 if (!job->IsWaiting()) |
| 139 continue; | 119 continue; |
| 140 | 120 |
| 141 bool should_wakeup = true; | 121 bool should_wakeup = true; |
| 142 const AddressList& address_list = job->address_list(); | 122 const AddressList& address_list = job->address_list(); |
| 143 for (const struct addrinfo* addrinfo = address_list.head(); | 123 for (AddressList::const_iterator addr_iter = address_list.begin(); |
| 144 addrinfo != NULL; | 124 addr_iter != address_list.end(); |
| 145 addrinfo = addrinfo->ai_next) { | 125 ++addr_iter) { |
| 146 std::string addrkey = AddrinfoToHashkey(addrinfo); | 126 std::string addrkey = IPEndPointToHashkey(*addr_iter); |
| 147 ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); | 127 ConnectingAddressMap::iterator iter = addr_map_.find(addrkey); |
| 148 DCHECK(iter != addr_map_.end()); | 128 DCHECK(iter != addr_map_.end()); |
| 149 ConnectingQueue* queue = iter->second; | 129 ConnectingQueue* queue = iter->second; |
| 150 if (job != queue->front()) { | 130 if (job != queue->front()) { |
| 151 should_wakeup = false; | 131 should_wakeup = false; |
| 152 break; | 132 break; |
| 153 } | 133 } |
| 154 } | 134 } |
| 155 if (should_wakeup) | 135 if (should_wakeup) |
| 156 job->Wakeup(); | 136 job->Wakeup(); |
| 157 } | 137 } |
| 158 } | 138 } |
| 159 | 139 |
| 160 } // namespace net | 140 } // namespace net |
| OLD | NEW |