Home | History | Annotate | Download | only in socket
      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 #ifndef NET_SOCKET_WEBSOCKET_ENDPOINT_LOCK_MANAGER_H_
      6 #define NET_SOCKET_WEBSOCKET_ENDPOINT_LOCK_MANAGER_H_
      7 
      8 #include <map>
      9 
     10 #include "base/containers/linked_list.h"
     11 #include "base/logging.h"
     12 #include "base/macros.h"
     13 #include "base/memory/singleton.h"
     14 #include "net/base/ip_endpoint.h"
     15 #include "net/base/net_export.h"
     16 #include "net/socket/websocket_transport_client_socket_pool.h"
     17 
     18 namespace net {
     19 
     20 class StreamSocket;
     21 
     22 class NET_EXPORT_PRIVATE WebSocketEndpointLockManager {
     23  public:
     24   class NET_EXPORT_PRIVATE Waiter : public base::LinkNode<Waiter> {
     25    public:
     26     // If the node is in a list, removes it.
     27     virtual ~Waiter();
     28 
     29     virtual void GotEndpointLock() = 0;
     30   };
     31 
     32   static WebSocketEndpointLockManager* GetInstance();
     33 
     34   // Returns OK if lock was acquired immediately, ERR_IO_PENDING if not. If the
     35   // lock was not acquired, then |waiter->GotEndpointLock()| will be called when
     36   // it is. A Waiter automatically removes itself from the list of waiters when
     37   // its destructor is called.
     38   int LockEndpoint(const IPEndPoint& endpoint, Waiter* waiter);
     39 
     40   // Records the IPEndPoint associated with a particular socket. This is
     41   // necessary because TCPClientSocket refuses to return the PeerAddress after
     42   // the connection is disconnected. The association will be forgotten when
     43   // UnlockSocket() or UnlockEndpoint() is called. The |socket| pointer must not
     44   // be deleted between the call to RememberSocket() and the call to
     45   // UnlockSocket().
     46   void RememberSocket(StreamSocket* socket, const IPEndPoint& endpoint);
     47 
     48   // Releases the lock on the endpoint that was associated with |socket| by
     49   // RememberSocket(). If appropriate, triggers the next socket connection.
     50   // Should be called exactly once for each |socket| that was passed to
     51   // RememberSocket(). Does nothing if UnlockEndpoint() has been called since
     52   // the call to RememberSocket().
     53   void UnlockSocket(StreamSocket* socket);
     54 
     55   // Releases the lock on |endpoint|. Does nothing if |endpoint| is not locked.
     56   // Removes any socket association that was recorded with RememberSocket(). If
     57   // appropriate, calls |waiter->GotEndpointLock()|.
     58   void UnlockEndpoint(const IPEndPoint& endpoint);
     59 
     60   // Checks that |lock_info_map_| and |socket_lock_info_map_| are empty. For
     61   // tests.
     62   bool IsEmpty() const;
     63 
     64  private:
     65   struct LockInfo {
     66     typedef base::LinkedList<Waiter> WaiterQueue;
     67 
     68     LockInfo();
     69     ~LockInfo();
     70 
     71     // This object must be copyable to be placed in the map, but it cannot be
     72     // copied after |queue| has been assigned to.
     73     LockInfo(const LockInfo& rhs);
     74 
     75     // Not used.
     76     LockInfo& operator=(const LockInfo& rhs);
     77 
     78     // Must be NULL to copy this object into the map. Must be set to non-NULL
     79     // after the object is inserted into the map then point to the same list
     80     // until this object is deleted.
     81     scoped_ptr<WaiterQueue> queue;
     82 
     83     // This pointer is only used to identify the last instance of StreamSocket
     84     // that was passed to RememberSocket() for this endpoint. It should only be
     85     // compared with other pointers. It is never dereferenced and not owned. It
     86     // is non-NULL if RememberSocket() has been called for this endpoint since
     87     // the last call to UnlockSocket() or UnlockEndpoint().
     88     StreamSocket* socket;
     89   };
     90 
     91   // SocketLockInfoMap requires std::map iterator semantics for LockInfoMap
     92   // (ie. that the iterator will remain valid as long as the entry is not
     93   // deleted).
     94   typedef std::map<IPEndPoint, LockInfo> LockInfoMap;
     95   typedef std::map<StreamSocket*, LockInfoMap::iterator> SocketLockInfoMap;
     96 
     97   WebSocketEndpointLockManager();
     98   ~WebSocketEndpointLockManager();
     99 
    100   void UnlockEndpointByIterator(LockInfoMap::iterator lock_info_it);
    101   void EraseSocket(LockInfoMap::iterator lock_info_it);
    102 
    103   // If an entry is present in the map for a particular endpoint, then that
    104   // endpoint is locked. If LockInfo.queue is non-empty, then one or more
    105   // Waiters are waiting for the lock.
    106   LockInfoMap lock_info_map_;
    107 
    108   // Store sockets remembered by RememberSocket() and not yet unlocked by
    109   // UnlockSocket() or UnlockEndpoint(). Every entry in this map always
    110   // references a live entry in lock_info_map_, and the LockInfo::socket member
    111   // is non-NULL if and only if there is an entry in this map for the socket.
    112   SocketLockInfoMap socket_lock_info_map_;
    113 
    114   friend struct DefaultSingletonTraits<WebSocketEndpointLockManager>;
    115 
    116   DISALLOW_COPY_AND_ASSIGN(WebSocketEndpointLockManager);
    117 };
    118 
    119 }  // namespace net
    120 
    121 #endif  // NET_SOCKET_WEBSOCKET_ENDPOINT_LOCK_MANAGER_H_
    122