1 // Copyright 2019 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 CAST_COMMON_CHANNEL_VIRTUAL_CONNECTION_ROUTER_H_
6 #define CAST_COMMON_CHANNEL_VIRTUAL_CONNECTION_ROUTER_H_
7 
8 #include <cstdint>
9 #include <map>
10 #include <memory>
11 #include <string>
12 
13 #include "absl/types/optional.h"
14 #include "cast/common/channel/proto/cast_channel.pb.h"
15 #include "cast/common/channel/virtual_connection.h"
16 #include "cast/common/public/cast_socket.h"
17 
18 namespace openscreen {
19 namespace cast {
20 
21 class CastMessageHandler;
22 class ConnectionNamespaceHandler;
23 
24 // Handles CastSockets by routing received messages to appropriate message
25 // handlers based on the VirtualConnection's local ID and sending messages over
26 // the appropriate CastSocket for a VirtualConnection.
27 //
28 // Basic model for using this would be:
29 //
30 // 1. Foo is a SenderSocketFactory::Client.
31 //
32 // 2. Foo calls SenderSocketFactory::Connect, optionally with VCRouter as the
33 //    CastSocket::Client.
34 //
35 // 3. Foo gets OnConnected callback and makes whatever local notes it needs
36 //    (e.g.  sink "resolved", init app probing state, etc.), then calls
37 //    VCRouter::TakeSocket.
38 //
39 // 4. Anything Foo wants to send (launch, app availability, etc.) goes through
40 //    VCRouter::Send via an appropriate VC.  The virtual connection is not
41 //    created automatically, so AddConnection() must be called first.
42 //
43 // 5. Anything Foo wants to receive must be registered with a handler by calling
44 //    AddHandlerForLocalId().
45 //
46 // 6. Foo is expected to clean-up after itself (#4 and #5) by calling
47 //    RemoveConnection() and RemoveHandlerForLocalId().
48 class VirtualConnectionRouter final : public CastSocket::Client {
49  public:
50   class SocketErrorHandler {
51    public:
52     virtual void OnClose(CastSocket* socket) = 0;
53     virtual void OnError(CastSocket* socket, Error error) = 0;
54   };
55 
56   VirtualConnectionRouter();
57   ~VirtualConnectionRouter() override;
58 
59   // Adds a VirtualConnection, if one does not already exist, to enable routing
60   // of peer-to-peer messages.
61   void AddConnection(VirtualConnection virtual_connection,
62                      VirtualConnection::AssociatedData associated_data);
63 
64   // Removes a VirtualConnection and returns true if a connection matching
65   // |virtual_connection| was found and removed.
66   bool RemoveConnection(const VirtualConnection& virtual_connection,
67                         VirtualConnection::CloseReason reason);
68 
69   // Removes all VirtualConnections whose local endpoint matches the given
70   // |local_id|.
71   void RemoveConnectionsByLocalId(const std::string& local_id);
72 
73   // Removes all VirtualConnections whose traffic passes over the socket
74   // referenced by |socket_id|.
75   void RemoveConnectionsBySocketId(int socket_id);
76 
77   // Returns the AssociatedData for a |virtual_connection| if a connection
78   // exists, nullopt otherwise. The pointer isn't stable in the long term; so,
79   // if it actually needs to be stored for later, the caller should make a copy.
80   absl::optional<const VirtualConnection::AssociatedData*> GetConnectionData(
81       const VirtualConnection& virtual_connection) const;
82 
83   // Adds/Removes a CastMessageHandler for all messages destined for the given
84   // |endpoint| referred to by |local_id|, and returns whether the given
85   // |local_id| was successfully added/removed.
86   //
87   // Note: Clients will need to separately call AddConnection(), and
88   // RemoveConnection() or RemoveConnectionsByLocalId().
89   bool AddHandlerForLocalId(std::string local_id, CastMessageHandler* endpoint);
90   bool RemoveHandlerForLocalId(const std::string& local_id);
91 
92   // |error_handler| must live until either its OnError or OnClose is called.
93   void TakeSocket(SocketErrorHandler* error_handler,
94                   std::unique_ptr<CastSocket> socket);
95   void CloseSocket(int id);
96 
97   Error Send(VirtualConnection virtual_conn,
98              ::cast::channel::CastMessage message);
99 
100   Error BroadcastFromLocalPeer(std::string local_id,
101                                ::cast::channel::CastMessage message);
102 
103   // CastSocket::Client overrides.
104   void OnError(CastSocket* socket, Error error) override;
105   void OnMessage(CastSocket* socket,
106                  ::cast::channel::CastMessage message) override;
107 
108  protected:
109   friend class ConnectionNamespaceHandler;
110 
set_connection_namespace_handler(ConnectionNamespaceHandler * handler)111   void set_connection_namespace_handler(ConnectionNamespaceHandler* handler) {
112     connection_handler_ = handler;
113   }
114 
115  private:
116   // This struct simply stores the remainder of the data {VirtualConnection,
117   // VirtualConnection::AssociatedData} that is not broken up into map keys for
118   // |connections_|.
119   struct VCTail {
120     std::string peer_id;
121     VirtualConnection::AssociatedData data;
122   };
123 
124   struct SocketWithHandler {
125     std::unique_ptr<CastSocket> socket;
126     SocketErrorHandler* error_handler;
127   };
128 
129   ConnectionNamespaceHandler* connection_handler_ = nullptr;
130 
131   std::map<int /* socket_id */,
132            std::multimap<std::string /* local_id */, VCTail>>
133       connections_;
134 
135   std::map<int, SocketWithHandler> sockets_;
136   std::map<std::string /* local_id */, CastMessageHandler*> endpoints_;
137 };
138 
139 }  // namespace cast
140 }  // namespace openscreen
141 
142 #endif  // CAST_COMMON_CHANNEL_VIRTUAL_CONNECTION_ROUTER_H_
143