| Index: net/socket/websocket_endpoint_lock_manager.cc
|
| diff --git a/net/socket/websocket_endpoint_lock_manager.cc b/net/socket/websocket_endpoint_lock_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c8d9a3b0a4602ab2cf93c249df3f2be34c7e5229
|
| --- /dev/null
|
| +++ b/net/socket/websocket_endpoint_lock_manager.cc
|
| @@ -0,0 +1,95 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "net/socket/websocket_endpoint_lock_manager.h"
|
| +
|
| +#include <utility>
|
| +
|
| +#include "base/logging.h"
|
| +#include "net/base/net_errors.h"
|
| +#include "net/base/net_log.h"
|
| +
|
| +namespace net {
|
| +
|
| +WebSocketEndpointLockManager::Waiter::~Waiter() {
|
| + if (next()) {
|
| + DCHECK(previous());
|
| + RemoveFromList();
|
| + }
|
| +}
|
| +
|
| +WebSocketEndpointLockManager* WebSocketEndpointLockManager::GetInstance() {
|
| + return Singleton<WebSocketEndpointLockManager>::get();
|
| +}
|
| +
|
| +int WebSocketEndpointLockManager::LockEndpoint(const IPEndPoint& endpoint,
|
| + Waiter* waiter) {
|
| + EndPointWaiterMap::value_type insert_value(endpoint, NULL);
|
| + std::pair<EndPointWaiterMap::iterator, bool> rv =
|
| + endpoint_waiter_map_.insert(insert_value);
|
| + if (rv.second) {
|
| + DVLOG(3) << "Locking endpoint " << endpoint.ToString();
|
| + rv.first->second = new ConnectJobQueue;
|
| + return OK;
|
| + }
|
| + DVLOG(3) << "Waiting for endpoint " << endpoint.ToString();
|
| + rv.first->second->Append(waiter);
|
| + return ERR_IO_PENDING;
|
| +}
|
| +
|
| +void WebSocketEndpointLockManager::RememberSocket(StreamSocket* socket,
|
| + const IPEndPoint& endpoint) {
|
| + bool inserted = socket_endpoint_map_.insert(SocketEndPointMap::value_type(
|
| + socket, endpoint)).second;
|
| + DCHECK(inserted);
|
| + DCHECK(endpoint_waiter_map_.find(endpoint) != endpoint_waiter_map_.end());
|
| + DVLOG(3) << "Remembered (StreamSocket*)" << socket << " for "
|
| + << endpoint.ToString() << " (" << socket_endpoint_map_.size()
|
| + << " sockets remembered)";
|
| +}
|
| +
|
| +void WebSocketEndpointLockManager::UnlockSocket(StreamSocket* socket) {
|
| + SocketEndPointMap::iterator socket_it = socket_endpoint_map_.find(socket);
|
| + if (socket_it == socket_endpoint_map_.end()) {
|
| + DVLOG(3) << "Ignoring request to unlock already-unlocked socket"
|
| + "(StreamSocket*)" << socket;
|
| + return;
|
| + }
|
| + const IPEndPoint& endpoint = socket_it->second;
|
| + DVLOG(3) << "Unlocking (StreamSocket*)" << socket << " for "
|
| + << endpoint.ToString() << " (" << socket_endpoint_map_.size()
|
| + << " sockets left)";
|
| + UnlockEndpoint(endpoint);
|
| + socket_endpoint_map_.erase(socket_it);
|
| +}
|
| +
|
| +void WebSocketEndpointLockManager::UnlockEndpoint(const IPEndPoint& endpoint) {
|
| + EndPointWaiterMap::iterator found_it = endpoint_waiter_map_.find(endpoint);
|
| + CHECK(found_it != endpoint_waiter_map_.end()); // Security critical
|
| + ConnectJobQueue* queue = found_it->second;
|
| + if (queue->empty()) {
|
| + DVLOG(3) << "Unlocking endpoint " << endpoint.ToString();
|
| + delete queue;
|
| + endpoint_waiter_map_.erase(found_it);
|
| + } else {
|
| + DVLOG(3) << "Unlocking endpoint " << endpoint.ToString()
|
| + << " and activating next waiter";
|
| + Waiter* next_job = queue->head()->value();
|
| + next_job->RemoveFromList();
|
| + next_job->GotEndpointLock();
|
| + }
|
| +}
|
| +
|
| +bool WebSocketEndpointLockManager::IsEmpty() const {
|
| + return endpoint_waiter_map_.empty() && socket_endpoint_map_.empty();
|
| +}
|
| +
|
| +WebSocketEndpointLockManager::WebSocketEndpointLockManager() {}
|
| +
|
| +WebSocketEndpointLockManager::~WebSocketEndpointLockManager() {
|
| + DCHECK(endpoint_waiter_map_.empty());
|
| + DCHECK(socket_endpoint_map_.empty());
|
| +}
|
| +
|
| +} // namespace net
|
|
|