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

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

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/socket/websocket_endpoint_lock_manager.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/net_log.h"
14
15 namespace net {
16
17 namespace {
18
19 // This delay prevents DoS attacks.
20 // TODO(ricea): Replace this with randomised truncated exponential backoff.
21 // See crbug.com/377613.
22 const int kUnlockDelayInMs = 10;
23
24 } // namespace
25
26 WebSocketEndpointLockManager::Waiter::~Waiter() {
27 if (next()) {
28 DCHECK(previous());
29 RemoveFromList();
30 }
31 }
32
33 WebSocketEndpointLockManager* WebSocketEndpointLockManager::GetInstance() {
34 return Singleton<WebSocketEndpointLockManager>::get();
35 }
36
37 int WebSocketEndpointLockManager::LockEndpoint(const IPEndPoint& endpoint,
38 Waiter* waiter) {
39 LockInfoMap::value_type insert_value(endpoint, LockInfo());
40 std::pair<LockInfoMap::iterator, bool> rv =
41 lock_info_map_.insert(insert_value);
42 LockInfo& lock_info_in_map = rv.first->second;
43 if (rv.second) {
44 DVLOG(3) << "Locking endpoint " << endpoint.ToString();
45 lock_info_in_map.queue.reset(new LockInfo::WaiterQueue);
46 return OK;
47 }
48 DVLOG(3) << "Waiting for endpoint " << endpoint.ToString();
49 lock_info_in_map.queue->Append(waiter);
50 return ERR_IO_PENDING;
51 }
52
53 void WebSocketEndpointLockManager::RememberSocket(StreamSocket* socket,
54 const IPEndPoint& endpoint) {
55 LockInfoMap::iterator lock_info_it = lock_info_map_.find(endpoint);
56 CHECK(lock_info_it != lock_info_map_.end());
57 bool inserted =
58 socket_lock_info_map_.insert(SocketLockInfoMap::value_type(
59 socket, lock_info_it)).second;
60 DCHECK(inserted);
61 DCHECK(!lock_info_it->second.socket);
62 lock_info_it->second.socket = socket;
63 DVLOG(3) << "Remembered (StreamSocket*)" << socket << " for "
64 << endpoint.ToString() << " (" << socket_lock_info_map_.size()
65 << " socket(s) remembered)";
66 }
67
68 void WebSocketEndpointLockManager::UnlockSocket(StreamSocket* socket) {
69 SocketLockInfoMap::iterator socket_it = socket_lock_info_map_.find(socket);
70 if (socket_it == socket_lock_info_map_.end())
71 return;
72
73 LockInfoMap::iterator lock_info_it = socket_it->second;
74
75 DVLOG(3) << "Unlocking (StreamSocket*)" << socket << " for "
76 << lock_info_it->first.ToString() << " ("
77 << socket_lock_info_map_.size() << " socket(s) left)";
78 socket_lock_info_map_.erase(socket_it);
79 DCHECK_EQ(socket, lock_info_it->second.socket);
80 lock_info_it->second.socket = NULL;
81 UnlockEndpointAfterDelay(lock_info_it->first);
82 }
83
84 void WebSocketEndpointLockManager::UnlockEndpoint(const IPEndPoint& endpoint) {
85 LockInfoMap::iterator lock_info_it = lock_info_map_.find(endpoint);
86 if (lock_info_it == lock_info_map_.end())
87 return;
88 if (lock_info_it->second.socket)
89 EraseSocket(lock_info_it);
90 UnlockEndpointAfterDelay(endpoint);
91 }
92
93 bool WebSocketEndpointLockManager::IsEmpty() const {
94 return lock_info_map_.empty() && socket_lock_info_map_.empty();
95 }
96
97 base::TimeDelta WebSocketEndpointLockManager::SetUnlockDelayForTesting(
98 base::TimeDelta new_delay) {
99 base::TimeDelta old_delay = unlock_delay_;
100 unlock_delay_ = new_delay;
101 return old_delay;
102 }
103
104 WebSocketEndpointLockManager::LockInfo::LockInfo() : socket(NULL) {}
105 WebSocketEndpointLockManager::LockInfo::~LockInfo() {
106 DCHECK(!socket);
107 }
108
109 WebSocketEndpointLockManager::LockInfo::LockInfo(const LockInfo& rhs)
110 : socket(rhs.socket) {
111 DCHECK(!rhs.queue);
112 }
113
114 WebSocketEndpointLockManager::WebSocketEndpointLockManager()
115 : unlock_delay_(base::TimeDelta::FromMilliseconds(kUnlockDelayInMs)),
116 pending_unlock_count_(0),
117 weak_factory_(this) {
118 }
119
120 WebSocketEndpointLockManager::~WebSocketEndpointLockManager() {
121 DCHECK_EQ(lock_info_map_.size(), pending_unlock_count_);
122 DCHECK(socket_lock_info_map_.empty());
123 }
124
125 void WebSocketEndpointLockManager::UnlockEndpointAfterDelay(
126 const IPEndPoint& endpoint) {
127 DVLOG(3) << "Delaying " << unlock_delay_.InMilliseconds()
128 << "ms before unlocking endpoint " << endpoint.ToString();
129 ++pending_unlock_count_;
130 base::MessageLoop::current()->PostDelayedTask(
131 FROM_HERE,
132 base::Bind(&WebSocketEndpointLockManager::DelayedUnlockEndpoint,
133 weak_factory_.GetWeakPtr(), endpoint),
134 unlock_delay_);
135 }
136
137 void WebSocketEndpointLockManager::DelayedUnlockEndpoint(
138 const IPEndPoint& endpoint) {
139 LockInfoMap::iterator lock_info_it = lock_info_map_.find(endpoint);
140 DCHECK_GT(pending_unlock_count_, 0U);
141 --pending_unlock_count_;
142 if (lock_info_it == lock_info_map_.end())
143 return;
144 DCHECK(!lock_info_it->second.socket);
145 LockInfo::WaiterQueue* queue = lock_info_it->second.queue.get();
146 DCHECK(queue);
147 if (queue->empty()) {
148 DVLOG(3) << "Unlocking endpoint " << lock_info_it->first.ToString();
149 lock_info_map_.erase(lock_info_it);
150 return;
151 }
152
153 DVLOG(3) << "Unlocking endpoint " << lock_info_it->first.ToString()
154 << " and activating next waiter";
155 Waiter* next_job = queue->head()->value();
156 next_job->RemoveFromList();
157 next_job->GotEndpointLock();
158 }
159
160 void WebSocketEndpointLockManager::EraseSocket(
161 LockInfoMap::iterator lock_info_it) {
162 DVLOG(3) << "Removing (StreamSocket*)" << lock_info_it->second.socket
163 << " for " << lock_info_it->first.ToString() << " ("
164 << socket_lock_info_map_.size() << " socket(s) left)";
165 size_t erased = socket_lock_info_map_.erase(lock_info_it->second.socket);
166 DCHECK_EQ(1U, erased);
167 lock_info_it->second.socket = NULL;
168 }
169
170 } // 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