Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Side by Side Diff: net/socket/websocket_endpoint_lock_manager.cc

Issue 436493002: Handle multiple simultanous wss: connections. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Two tiny comment fixes. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/websocket_endpoint_lock_manager.h" 5 #include "net/socket/websocket_endpoint_lock_manager.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "net/base/net_errors.h" 10 #include "net/base/net_errors.h"
11 #include "net/base/net_log.h" 11 #include "net/base/net_log.h"
12 12
13 namespace net { 13 namespace net {
14 14
15 WebSocketEndpointLockManager::Waiter::~Waiter() { 15 WebSocketEndpointLockManager::Waiter::~Waiter() {
16 if (next()) { 16 if (next()) {
17 DCHECK(previous()); 17 DCHECK(previous());
18 RemoveFromList(); 18 RemoveFromList();
19 } 19 }
20 } 20 }
21 21
22 WebSocketEndpointLockManager* WebSocketEndpointLockManager::GetInstance() { 22 WebSocketEndpointLockManager* WebSocketEndpointLockManager::GetInstance() {
23 return Singleton<WebSocketEndpointLockManager>::get(); 23 return Singleton<WebSocketEndpointLockManager>::get();
24 } 24 }
25 25
26 int WebSocketEndpointLockManager::LockEndpoint(const IPEndPoint& endpoint, 26 int WebSocketEndpointLockManager::LockEndpoint(const IPEndPoint& endpoint,
27 Waiter* waiter) { 27 Waiter* waiter) {
28 EndPointWaiterMap::value_type insert_value(endpoint, NULL); 28 LockInfoMap::value_type insert_value(endpoint, LockInfo());
29 std::pair<EndPointWaiterMap::iterator, bool> rv = 29 std::pair<LockInfoMap::iterator, bool> rv =
30 endpoint_waiter_map_.insert(insert_value); 30 lock_info_map_.insert(insert_value);
31 if (rv.second) { 31 if (rv.second) {
32 DVLOG(3) << "Locking endpoint " << endpoint.ToString(); 32 DVLOG(3) << "Locking endpoint " << endpoint.ToString();
33 rv.first->second = new ConnectJobQueue; 33 rv.first->second.queue.reset(new LockInfo::WaiterQueue);
34 return OK; 34 return OK;
35 } 35 }
36 DVLOG(3) << "Waiting for endpoint " << endpoint.ToString(); 36 DVLOG(3) << "Waiting for endpoint " << endpoint.ToString();
37 rv.first->second->Append(waiter); 37 rv.first->second.queue->Append(waiter);
38 return ERR_IO_PENDING; 38 return ERR_IO_PENDING;
39 } 39 }
40 40
41 void WebSocketEndpointLockManager::RememberSocket(StreamSocket* socket, 41 void WebSocketEndpointLockManager::RememberSocket(StreamSocket* socket,
42 const IPEndPoint& endpoint) { 42 const IPEndPoint& endpoint) {
43 bool inserted = socket_endpoint_map_.insert(SocketEndPointMap::value_type( 43 LockInfoMap::iterator lock_info_it = lock_info_map_.find(endpoint);
44 socket, endpoint)).second; 44 CHECK(lock_info_it != lock_info_map_.end());
45 bool inserted =
46 socket_lock_info_map_.insert(SocketLockInfoMap::value_type(
47 socket, lock_info_it)).second;
45 DCHECK(inserted); 48 DCHECK(inserted);
46 DCHECK(endpoint_waiter_map_.find(endpoint) != endpoint_waiter_map_.end()); 49 DCHECK(!lock_info_it->second.socket);
50 lock_info_it->second.socket = socket;
47 DVLOG(3) << "Remembered (StreamSocket*)" << socket << " for " 51 DVLOG(3) << "Remembered (StreamSocket*)" << socket << " for "
48 << endpoint.ToString() << " (" << socket_endpoint_map_.size() 52 << endpoint.ToString() << " (" << socket_lock_info_map_.size()
49 << " sockets remembered)"; 53 << " socket(s) remembered)";
50 } 54 }
51 55
52 void WebSocketEndpointLockManager::UnlockSocket(StreamSocket* socket) { 56 void WebSocketEndpointLockManager::UnlockSocket(StreamSocket* socket) {
53 SocketEndPointMap::iterator socket_it = socket_endpoint_map_.find(socket); 57 SocketLockInfoMap::iterator socket_it = socket_lock_info_map_.find(socket);
54 if (socket_it == socket_endpoint_map_.end()) { 58 if (socket_it == socket_lock_info_map_.end())
55 DVLOG(3) << "Ignoring request to unlock already-unlocked socket"
56 "(StreamSocket*)" << socket;
57 return; 59 return;
58 } 60
59 const IPEndPoint& endpoint = socket_it->second; 61 LockInfoMap::iterator lock_info_it = socket_it->second;
62
60 DVLOG(3) << "Unlocking (StreamSocket*)" << socket << " for " 63 DVLOG(3) << "Unlocking (StreamSocket*)" << socket << " for "
61 << endpoint.ToString() << " (" << socket_endpoint_map_.size() 64 << lock_info_it->first.ToString() << " ("
62 << " sockets left)"; 65 << socket_lock_info_map_.size() << " socket(s) left)";
63 UnlockEndpoint(endpoint); 66 socket_lock_info_map_.erase(socket_it);
64 socket_endpoint_map_.erase(socket_it); 67 DCHECK(socket == lock_info_it->second.socket);
68 lock_info_it->second.socket = NULL;
69 UnlockEndpointByIterator(lock_info_it);
65 } 70 }
66 71
67 void WebSocketEndpointLockManager::UnlockEndpoint(const IPEndPoint& endpoint) { 72 void WebSocketEndpointLockManager::UnlockEndpoint(const IPEndPoint& endpoint) {
68 EndPointWaiterMap::iterator found_it = endpoint_waiter_map_.find(endpoint); 73 LockInfoMap::iterator lock_info_it = lock_info_map_.find(endpoint);
69 CHECK(found_it != endpoint_waiter_map_.end()); // Security critical 74 if (lock_info_it == lock_info_map_.end())
70 ConnectJobQueue* queue = found_it->second; 75 return;
71 if (queue->empty()) { 76
72 DVLOG(3) << "Unlocking endpoint " << endpoint.ToString(); 77 UnlockEndpointByIterator(lock_info_it);
73 delete queue;
74 endpoint_waiter_map_.erase(found_it);
75 } else {
76 DVLOG(3) << "Unlocking endpoint " << endpoint.ToString()
77 << " and activating next waiter";
78 Waiter* next_job = queue->head()->value();
79 next_job->RemoveFromList();
80 next_job->GotEndpointLock();
81 }
82 } 78 }
83 79
84 bool WebSocketEndpointLockManager::IsEmpty() const { 80 bool WebSocketEndpointLockManager::IsEmpty() const {
85 return endpoint_waiter_map_.empty() && socket_endpoint_map_.empty(); 81 return lock_info_map_.empty() && socket_lock_info_map_.empty();
82 }
83
84 WebSocketEndpointLockManager::LockInfo::LockInfo() : socket(NULL) {}
85 WebSocketEndpointLockManager::LockInfo::~LockInfo() {
86 DCHECK(!socket);
87 }
88
89 WebSocketEndpointLockManager::LockInfo::LockInfo(const LockInfo& rhs)
90 : socket(rhs.socket) {
91 DCHECK(!rhs.queue);
86 } 92 }
87 93
88 WebSocketEndpointLockManager::WebSocketEndpointLockManager() {} 94 WebSocketEndpointLockManager::WebSocketEndpointLockManager() {}
89 95
90 WebSocketEndpointLockManager::~WebSocketEndpointLockManager() { 96 WebSocketEndpointLockManager::~WebSocketEndpointLockManager() {
91 DCHECK(endpoint_waiter_map_.empty()); 97 DCHECK(lock_info_map_.empty());
92 DCHECK(socket_endpoint_map_.empty()); 98 DCHECK(socket_lock_info_map_.empty());
99 }
100
101 void WebSocketEndpointLockManager::UnlockEndpointByIterator(
102 LockInfoMap::iterator lock_info_it) {
103 if (lock_info_it->second.socket)
104 EraseSocket(lock_info_it);
105 scoped_ptr<LockInfo::WaiterQueue>& queue = lock_info_it->second.queue;
tyoshino (SeeGerritForStatus) 2014/08/01 11:31:44 how about just using a pointer?
Adam Rice 2014/08/01 14:09:39 Done.
106 if (queue->empty()) {
107 DVLOG(3) << "Unlocking endpoint " << lock_info_it->first.ToString();
108 queue.reset();
tyoshino (SeeGerritForStatus) 2014/08/01 11:31:44 then, you need to call it on to lock_info_it->seco
Adam Rice 2014/08/01 14:09:39 I just removed the reset() completely, since the s
109 lock_info_map_.erase(lock_info_it);
110 return;
111 }
112
113 DVLOG(3) << "Unlocking endpoint " << lock_info_it->first.ToString()
114 << " and activating next waiter";
115 Waiter* next_job = queue->head()->value();
116 next_job->RemoveFromList();
117 // This must be last to minimise the excitement caused by re-entrancy.
118 next_job->GotEndpointLock();
119 }
120
121 void WebSocketEndpointLockManager::EraseSocket(
122 LockInfoMap::iterator lock_info_it) {
123 DVLOG(3) << "Removing (StreamSocket*)" << lock_info_it->second.socket
124 << " for " << lock_info_it->first.ToString() << " ("
125 << socket_lock_info_map_.size() << " socket(s) left)";
126 size_t erased = socket_lock_info_map_.erase(lock_info_it->second.socket);
127 DCHECK_EQ(1U, erased);
128 lock_info_it->second.socket = NULL;
93 } 129 }
94 130
95 } // namespace net 131 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/websocket_endpoint_lock_manager.h ('k') | net/socket/websocket_endpoint_lock_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698