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