• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_IMPL_QUIC_QUIC_CLIENT_H_
6 #define OSP_IMPL_QUIC_QUIC_CLIENT_H_
7 
8 #include <cstdint>
9 #include <map>
10 #include <memory>
11 #include <vector>
12 
13 #include "osp/impl/quic/quic_connection_factory.h"
14 #include "osp/impl/quic/quic_service_common.h"
15 #include "osp/public/protocol_connection_client.h"
16 #include "platform/api/task_runner.h"
17 #include "platform/api/time.h"
18 #include "platform/base/ip_address.h"
19 #include "util/alarm.h"
20 
21 namespace openscreen {
22 namespace osp {
23 
24 // This class is the default implementation of ProtocolConnectionClient for the
25 // library.  It manages connections to other endpoints as well as the lifetime
26 // of each incoming and outgoing stream.  It works in conjunction with a
27 // QuicConnectionFactory implementation and MessageDemuxer.
28 // QuicConnectionFactory provides the actual ability to make a new QUIC
29 // connection with another endpoint.  Incoming data is given to the QuicClient
30 // by the underlying QUIC implementation (through QuicConnectionFactory) and
31 // this is in turn handed to MessageDemuxer for routing CBOR messages.
32 //
33 // The two most significant methods of this class are Connect and
34 // CreateProtocolConnection.  Both will return a new QUIC stream to a given
35 // endpoint to which the caller can write but the former is allowed to be
36 // asynchronous.  If there isn't currently a connection to the specified
37 // endpoint, Connect will start a connection attempt and store the callback for
38 // when the connection completes.  CreateProtocolConnection simply returns
39 // nullptr if there's no existing connection.
40 class QuicClient final : public ProtocolConnectionClient,
41                          public ServiceConnectionDelegate::ServiceDelegate {
42  public:
43   QuicClient(MessageDemuxer* demuxer,
44              std::unique_ptr<QuicConnectionFactory> connection_factory,
45              ProtocolConnectionServiceObserver* observer,
46              ClockNowFunctionPtr now_function,
47              TaskRunner* task_runner);
48   ~QuicClient() override;
49 
50   // ProtocolConnectionClient overrides.
51   bool Start() override;
52   bool Stop() override;
53   ConnectRequest Connect(const IPEndpoint& endpoint,
54                          ConnectionRequestCallback* request) override;
55   std::unique_ptr<ProtocolConnection> CreateProtocolConnection(
56       uint64_t endpoint_id) override;
57 
58   // QuicProtocolConnection::Owner overrides.
59   void OnConnectionDestroyed(QuicProtocolConnection* connection) override;
60 
61   // ServiceConnectionDelegate::ServiceDelegate overrides.
62   uint64_t OnCryptoHandshakeComplete(ServiceConnectionDelegate* delegate,
63                                      uint64_t connection_id) override;
64   void OnIncomingStream(
65       std::unique_ptr<QuicProtocolConnection> connection) override;
66   void OnConnectionClosed(uint64_t endpoint_id,
67                           uint64_t connection_id) override;
68   void OnDataReceived(uint64_t endpoint_id,
69                       uint64_t connection_id,
70                       const uint8_t* data,
71                       size_t data_size) override;
72 
73  private:
74   struct PendingConnectionData {
75     explicit PendingConnectionData(ServiceConnectionData&& data);
76     PendingConnectionData(PendingConnectionData&&) noexcept;
77     ~PendingConnectionData();
78     PendingConnectionData& operator=(PendingConnectionData&&) noexcept;
79 
80     ServiceConnectionData data;
81 
82     // Pairs of request IDs and the associated connection callback.
83     std::vector<std::pair<uint64_t, ConnectionRequestCallback*>> callbacks;
84   };
85 
86   ConnectRequest CreatePendingConnection(const IPEndpoint& endpoint,
87                                          ConnectionRequestCallback* request);
88   uint64_t StartConnectionRequest(const IPEndpoint& endpoint,
89                                   ConnectionRequestCallback* request);
90   void CloseAllConnections();
91   std::unique_ptr<QuicProtocolConnection> MakeProtocolConnection(
92       QuicConnection* connection,
93       ServiceConnectionDelegate* delegate,
94       uint64_t endpoint_id);
95 
96   void CancelConnectRequest(uint64_t request_id) override;
97 
98   // Deletes dead QUIC connections then returns the time interval before this
99   // method should be run again.
100   void Cleanup();
101 
102   std::unique_ptr<QuicConnectionFactory> connection_factory_;
103 
104   // Maps an IPEndpoint to a generated endpoint ID.  This is used to insulate
105   // callers from post-handshake changes to a connections actual peer endpoint.
106   std::map<IPEndpoint, uint64_t> endpoint_map_;
107 
108   // Value that will be used for the next new endpoint in a Connect call.
109   uint64_t next_endpoint_id_ = 0;
110 
111   // Maps request IDs to their callbacks.  The callback is paired with the
112   // IPEndpoint it originally requested to connect to so cancelling the request
113   // can also remove a pending connection.
114   std::map<uint64_t, std::pair<IPEndpoint, ConnectionRequestCallback*>>
115       request_map_;
116 
117   // Value that will be used for the next new connection request.
118   uint64_t next_request_id_ = 1;
119 
120   // Maps endpoint addresses to data about connections that haven't successfully
121   // completed the QUIC handshake.
122   std::map<IPEndpoint, PendingConnectionData> pending_connections_;
123 
124   // Maps endpoint IDs to data about connections that have successfully
125   // completed the QUIC handshake.
126   std::map<uint64_t, ServiceConnectionData> connections_;
127 
128   // Connections (endpoint IDs) that need to be destroyed, but have to wait for
129   // the next event loop due to the underlying QUIC implementation's way of
130   // referencing them.
131   std::vector<uint64_t> delete_connections_;
132 
133   Alarm cleanup_alarm_;
134 };
135 
136 }  // namespace osp
137 }  // namespace openscreen
138 
139 #endif  // OSP_IMPL_QUIC_QUIC_CLIENT_H_
140