websocket_endpoint_lock_manager.h revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifndef NET_SOCKET_WEBSOCKET_ENDPOINT_LOCK_MANAGER_H_ 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define NET_SOCKET_WEBSOCKET_ENDPOINT_LOCK_MANAGER_H_ 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <map> 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/containers/linked_list.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/logging.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/macros.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/memory/singleton.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/ip_endpoint.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/net_export.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/socket/websocket_transport_client_socket_pool.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace net { 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass StreamSocket; 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass NET_EXPORT_PRIVATE WebSocketEndpointLockManager { 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public: 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch class NET_EXPORT_PRIVATE Waiter : public base::LinkNode<Waiter> { 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public: 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If the node is in a list, removes it. 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual ~Waiter(); 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void GotEndpointLock() = 0; 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }; 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static WebSocketEndpointLockManager* GetInstance(); 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Returns OK if lock was acquired immediately, ERR_IO_PENDING if not. If the 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // lock was not acquired, then |waiter->GotEndpointLock()| will be called when 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // it is. A Waiter automatically removes itself from the list of waiters when 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // its destructor is called. 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int LockEndpoint(const IPEndPoint& endpoint, Waiter* waiter); 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Records the IPEndPoint associated with a particular socket. This is 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // necessary because TCPClientSocket refuses to return the PeerAddress after 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the connection is disconnected. The association will be forgotten when 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // UnlockSocket() or UnlockEndpoint() is called. The |socket| pointer must not 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // be deleted between the call to RememberSocket() and the call to 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // UnlockSocket(). 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void RememberSocket(StreamSocket* socket, const IPEndPoint& endpoint); 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Releases the lock on the endpoint that was associated with |socket| by 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // RememberSocket(). If appropriate, triggers the next socket connection. 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Should be called exactly once for each |socket| that was passed to 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // RememberSocket(). Does nothing if UnlockEndpoint() has been called since 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the call to RememberSocket(). 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void UnlockSocket(StreamSocket* socket); 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Releases the lock on |endpoint|. Does nothing if |endpoint| is not locked. 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Removes any socket association that was recorded with RememberSocket(). If 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // appropriate, calls |waiter->GotEndpointLock()|. 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void UnlockEndpoint(const IPEndPoint& endpoint); 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Checks that |lock_info_map_| and |socket_lock_info_map_| are empty. For 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // tests. 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool IsEmpty() const; 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct LockInfo { 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) typedef base::LinkedList<Waiter> WaiterQueue; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LockInfo(); 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ~LockInfo(); 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This object must be copyable to be placed in the map, but it cannot be 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // copied after |queue| has been assigned to. 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LockInfo(const LockInfo& rhs); 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Not used. 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LockInfo& operator=(const LockInfo& rhs); 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Must be NULL to copy this object into the map. Must be set to non-NULL 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // after the object is inserted into the map then point to the same list 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // until this object is deleted. 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<WaiterQueue> queue; 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This pointer is only used to identify the last instance of StreamSocket 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // that was passed to RememberSocket() for this endpoint. It should only be 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // compared with other pointers. It is never dereferenced and not owned. It 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // is non-NULL if RememberSocket() has been called for this endpoint since 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the last call to UnlockSocket() or UnlockEndpoint(). 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) StreamSocket* socket; 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // SocketLockInfoMap requires std::map iterator semantics for LockInfoMap 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // (ie. that the iterator will remain valid as long as the entry is not 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // deleted). 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) typedef std::map<IPEndPoint, LockInfo> LockInfoMap; 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) typedef std::map<StreamSocket*, LockInfoMap::iterator> SocketLockInfoMap; 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WebSocketEndpointLockManager(); 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ~WebSocketEndpointLockManager(); 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void UnlockEndpointByIterator(LockInfoMap::iterator lock_info_it); 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void EraseSocket(LockInfoMap::iterator lock_info_it); 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If an entry is present in the map for a particular endpoint, then that 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // endpoint is locked. If LockInfo.queue is non-empty, then one or more 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Waiters are waiting for the lock. 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LockInfoMap lock_info_map_; 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Store sockets remembered by RememberSocket() and not yet unlocked by 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // UnlockSocket() or UnlockEndpoint(). Every entry in this map always 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // references a live entry in lock_info_map_, and the LockInfo::socket member 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // is non-NULL if and only if there is an entry in this map for the socket. 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SocketLockInfoMap socket_lock_info_map_; 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch friend struct DefaultSingletonTraits<WebSocketEndpointLockManager>; 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DISALLOW_COPY_AND_ASSIGN(WebSocketEndpointLockManager); 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace net 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif // NET_SOCKET_WEBSOCKET_ENDPOINT_LOCK_MANAGER_H_ 122