• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 OSP_PUBLIC_PRESENTATION_PRESENTATION_CONNECTION_H_
6 #define OSP_PUBLIC_PRESENTATION_PRESENTATION_CONNECTION_H_
7 
8 #include <cstdint>
9 #include <map>
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "absl/strings/string_view.h"
15 #include "absl/types/optional.h"
16 #include "osp/public/message_demuxer.h"
17 #include "platform/api/time.h"
18 #include "platform/base/error.h"
19 #include "platform/base/ip_address.h"
20 #include "platform/base/macros.h"
21 #include "util/osp_logging.h"
22 
23 namespace openscreen {
24 namespace osp {
25 
26 class ProtocolConnection;
27 
28 enum class TerminationReason {
29   kReceiverTerminateCalled = 0,
30   kReceiverUserTerminated,
31   kControllerTerminateCalled,
32   kControllerUserTerminated,
33   kReceiverPresentationReplaced,
34   kReceiverIdleTooLong,
35   kReceiverPresentationUnloaded,
36   kReceiverShuttingDown,
37   kReceiverError,
38 };
39 
40 class Connection {
41  public:
42   enum class CloseReason {
43     kClosed = 0,
44     kDiscarded,
45     kError,
46   };
47 
48   enum class State {
49     // The library is currently attempting to connect to the presentation.
50     kConnecting,
51     // The connection to the presentation is open and communication is possible.
52     kConnected,
53     // The connection is closed or could not be opened.  No communication is
54     // possible but it may be possible to reopen the connection via
55     // ReconnectPresentation.
56     kClosed,
57     // The connection is closed and the receiver has been terminated.
58     kTerminated,
59   };
60 
61   // An object to receive callbacks related to a single Connection.
62   class Delegate {
63    public:
64     Delegate() = default;
65 
66     // State changes.
67     virtual void OnConnected() = 0;
68 
69     // Explicit close by other endpoint.
70     virtual void OnClosedByRemote() = 0;
71 
72     // Closed because the script connection object was discarded.
73     virtual void OnDiscarded() = 0;
74 
75     // Closed because of an error.
76     virtual void OnError(const absl::string_view message) = 0;
77 
78     // Terminated through a different connection.
79     virtual void OnTerminated() = 0;
80 
81     // A UTF-8 string message was received.
82     virtual void OnStringMessage(const absl::string_view message) = 0;
83 
84     // A binary message was received.
85     virtual void OnBinaryMessage(const std::vector<uint8_t>& data) = 0;
86 
87    protected:
88     virtual ~Delegate() = default;
89 
90    private:
91     OSP_DISALLOW_COPY_AND_ASSIGN(Delegate);
92   };
93 
94   // Allows different close, termination, and destruction behavior for both
95   // possible parents: controller and receiver.  This is different from the
96   // normal delegate above, which would be supplied by the embedder to link it's
97   // presentation connection functionality.
98   class ParentDelegate {
99    public:
100     ParentDelegate() = default;
101     virtual ~ParentDelegate() = default;
102 
103     virtual Error CloseConnection(Connection* connection,
104                                   CloseReason reason) = 0;
105     virtual Error OnPresentationTerminated(const std::string& presentation_id,
106                                            TerminationReason reason) = 0;
107     virtual void OnConnectionDestroyed(Connection* connection) = 0;
108 
109    private:
110     OSP_DISALLOW_COPY_AND_ASSIGN(ParentDelegate);
111   };
112 
113   struct PresentationInfo {
114     std::string id;
115     std::string url;
116   };
117 
118   // Constructs a new connection using |delegate| for callbacks.
119   Connection(const PresentationInfo& info,
120              Delegate* delegate,
121              ParentDelegate* parent_delegate);
122   ~Connection();
123 
124   // Returns the ID and URL of this presentation.
presentation_info()125   const PresentationInfo& presentation_info() const { return presentation_; }
126 
state()127   State state() const { return state_; }
128 
get_protocol_connection()129   ProtocolConnection* get_protocol_connection() const {
130     return protocol_connection_.get();
131   }
132 
133   // These methods should only be called when we are connected.
endpoint_id()134   uint64_t endpoint_id() const {
135     OSP_CHECK(endpoint_id_);
136     return endpoint_id_.value();
137   }
connection_id()138   uint64_t connection_id() const {
139     OSP_CHECK(connection_id_);
140     return connection_id_.value();
141   }
142 
143   // Sends a UTF-8 string message.
144   Error SendString(absl::string_view message);
145 
146   // Sends a binary message.
147   Error SendBinary(std::vector<uint8_t>&& data);
148 
149   // Closes the connection.  This can be based on an explicit request from the
150   // embedder or because the connection object is being discarded (page
151   // navigated, object GC'd, etc.).
152   Error Close(CloseReason reason);
153 
154   // Terminates the presentation associated with this connection.
155   void Terminate(TerminationReason reason);
156 
157   void OnConnecting();
158 
159   // Called by the receiver when the OnPresentationStarted logic happens. This
160   // notifies the delegate and updates our internal stream and ids.
161   void OnConnected(uint64_t connection_id,
162                    uint64_t endpoint_id,
163                    std::unique_ptr<ProtocolConnection> stream);
164 
165   void OnClosedByError(Error cause);
166   void OnClosedByRemote();
167   void OnTerminated();
168 
get_delegate()169   Delegate* get_delegate() { return delegate_; }
170 
171  private:
172   // Helper method that handles closing down our internal state.
173   // Returns whether or not the connection state changed (and thus
174   // whether or not delegates should be informed).
175   bool OnClosed();
176 
177   PresentationInfo presentation_;
178   State state_ = State::kConnecting;
179   Delegate* delegate_;
180   ParentDelegate* parent_delegate_;
181   absl::optional<uint64_t> connection_id_;
182   absl::optional<uint64_t> endpoint_id_;
183   std::unique_ptr<ProtocolConnection> protocol_connection_;
184 
185   OSP_DISALLOW_COPY_AND_ASSIGN(Connection);
186 };
187 
188 class ConnectionManager final : public MessageDemuxer::MessageCallback {
189  public:
190   explicit ConnectionManager(MessageDemuxer* demuxer);
191 
192   void AddConnection(Connection* connection);
193   void RemoveConnection(Connection* connection);
194 
195   // MessasgeDemuxer::MessageCallback overrides.
196   ErrorOr<size_t> OnStreamMessage(uint64_t endpoint_id,
197                                   uint64_t connection_id,
198                                   msgs::Type message_type,
199                                   const uint8_t* buffer,
200                                   size_t buffer_size,
201                                   Clock::time_point now) override;
202 
203   Connection* GetConnection(uint64_t connection_id);
204 
205  private:
206   // TODO(btolsch): Connection IDs were changed to be per-endpoint, but this
207   // table then needs to be <endpoint id, connection id> since connection id is
208   // still not unique globally.
209   std::map<uint64_t, Connection*> connections_;
210 
211   MessageDemuxer::MessageWatch message_watch_;
212   MessageDemuxer::MessageWatch close_request_watch_;
213   MessageDemuxer::MessageWatch close_event_watch_;
214 
215   OSP_DISALLOW_COPY_AND_ASSIGN(ConnectionManager);
216 };
217 
218 }  // namespace osp
219 }  // namespace openscreen
220 
221 #endif  // OSP_PUBLIC_PRESENTATION_PRESENTATION_CONNECTION_H_
222