1 // Copyright 2018 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_PROTOCOL_CONNECTION_H_
6 #define OSP_PUBLIC_PROTOCOL_CONNECTION_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <type_traits>
11 
12 #include "osp/msgs/osp_messages.h"
13 #include "platform/base/error.h"
14 #include "util/osp_logging.h"
15 
16 namespace openscreen {
17 
18 class Error;
19 
20 namespace osp {
21 
22 template <typename T>
23 using MessageEncodingFunction =
24     std::add_pointer_t<bool(const T&, msgs::CborEncodeBuffer*)>;
25 
26 struct NetworkMetrics;
27 
28 // Represents an embedder's view of a connection between an Open Screen
29 // controller and a receiver.  Both the controller and receiver will have a
30 // ProtocolConnection object, although the information known about the other
31 // party may not be symmetrical.
32 //
33 // A ProtocolConnection supports multiple protocols defined by the Open Screen
34 // standard and can be extended by embedders with additional protocols.
35 //
36 // TODO(jophba): move to sharing underlying QUIC connections between multiple
37 // instances of ProtocolConnection.
38 class ProtocolConnection {
39  public:
40   class Observer {
41    public:
42     virtual ~Observer() = default;
43 
44     // Called when |connection| is no longer available, either because the
45     // underlying transport was terminated, the underying system resource was
46     // closed, or data can no longer be exchanged.
47     virtual void OnConnectionClosed(const ProtocolConnection& connection) = 0;
48   };
49 
50   ProtocolConnection(uint64_t endpoint_id, uint64_t connection_id);
51   virtual ~ProtocolConnection() = default;
52 
53   // TODO(mfoltz): Define extension API exposed to embedders.  This would be
54   // used, for example, to query for and implement vendor-specific protocols
55   // alongside the Open Screen Protocol.
56 
57   // NOTE: ProtocolConnection instances that are owned by clients will have a
58   // ServiceInfo attached with data from discovery and QUIC connection
59   // establishment.  What about server connections?  We probably want to have
60   // two different structures representing what the client and server know about
61   // a connection.
62 
63   void SetObserver(Observer* observer);
64 
65   template <typename T>
WriteMessage(const T & message,MessageEncodingFunction<T> encoder)66   Error WriteMessage(const T& message, MessageEncodingFunction<T> encoder) {
67     msgs::CborEncodeBuffer buffer;
68 
69     if (!encoder(message, &buffer)) {
70       OSP_LOG_WARN << "failed to properly encode presentation message";
71       return Error::Code::kParseError;
72     }
73 
74     Write(buffer.data(), buffer.size());
75 
76     return Error::None();
77   }
78 
79   // TODO(btolsch): This should be derived from the handshake auth identifier
80   // when that is finalized and implemented.
endpoint_id()81   uint64_t endpoint_id() const { return endpoint_id_; }
id()82   uint64_t id() const { return id_; }
83 
84   virtual void Write(const uint8_t* data, size_t data_size) = 0;
85   virtual void CloseWriteEnd() = 0;
86 
87  protected:
88   uint64_t endpoint_id_;
89   uint64_t id_;
90   Observer* observer_ = nullptr;
91 };
92 
93 class ProtocolConnectionServiceObserver {
94  public:
95   // Called when the state becomes kRunning.
96   virtual void OnRunning() = 0;
97   // Called when the state becomes kStopped.
98   virtual void OnStopped() = 0;
99 
100   // Called when metrics have been collected by the service.
101   virtual void OnMetrics(const NetworkMetrics& metrics) = 0;
102   // Called when an error has occurred.
103   virtual void OnError(const Error& error) = 0;
104 
105  protected:
106   virtual ~ProtocolConnectionServiceObserver() = default;
107 };
108 
109 }  // namespace osp
110 }  // namespace openscreen
111 
112 #endif  // OSP_PUBLIC_PROTOCOL_CONNECTION_H_
113