1 // Copyright (c) 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 QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_H_
6 #define QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_H_
7 
8 #include <cstdint>
9 #include <memory>
10 
11 #include "url/gurl.h"
12 #include "url/origin.h"
13 #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
14 #include "net/third_party/quiche/src/quic/core/quic_config.h"
15 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
16 #include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h"
17 #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
18 #include "net/third_party/quiche/src/quic/core/quic_server_id.h"
19 #include "net/third_party/quiche/src/quic/core/quic_session.h"
20 #include "net/third_party/quiche/src/quic/core/quic_stream.h"
21 #include "net/third_party/quiche/src/quic/core/quic_versions.h"
22 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
23 #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
24 #include "net/third_party/quiche/src/quic/quic_transport/quic_transport_protocol.h"
25 #include "net/third_party/quiche/src/quic/quic_transport/quic_transport_session_interface.h"
26 #include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
27 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
28 
29 namespace quic {
30 
31 // A client session for the QuicTransport protocol.
32 class QUIC_EXPORT_PRIVATE QuicTransportClientSession
33     : public QuicSession,
34       public QuicTransportSessionInterface {
35  public:
36   class QUIC_EXPORT_PRIVATE ClientVisitor {
37    public:
~ClientVisitor()38     virtual ~ClientVisitor() {}
39 
40     // Notifies the visitor when the client indication has been sent and the
41     // connection is ready to exchange application data.
42     virtual void OnSessionReady() = 0;
43 
44     // Notifies the visitor when a new stream has been received.  The stream in
45     // question can be retrieved using AcceptIncomingBidirectionalStream() or
46     // AcceptIncomingUnidirectionalStream().
47     virtual void OnIncomingBidirectionalStreamAvailable() = 0;
48     virtual void OnIncomingUnidirectionalStreamAvailable() = 0;
49 
50     // Notifies the visitor when a new datagram has been received.
51     virtual void OnDatagramReceived(quiche::QuicheStringPiece datagram) = 0;
52 
53     // Notifies the visitor that a new outgoing stream can now be created.
54     virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0;
55     virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0;
56   };
57 
58   QuicTransportClientSession(QuicConnection* connection,
59                              Visitor* owner,
60                              const QuicConfig& config,
61                              const ParsedQuicVersionVector& supported_versions,
62                              const GURL& url,
63                              QuicCryptoClientConfig* crypto_config,
64                              url::Origin origin,
65                              ClientVisitor* visitor);
66 
GetAlpnsToOffer()67   std::vector<std::string> GetAlpnsToOffer() const override {
68     return std::vector<std::string>({QuicTransportAlpn()});
69   }
70   void OnAlpnSelected(quiche::QuicheStringPiece alpn) override;
alpn_received()71   bool alpn_received() const { return alpn_received_; }
72 
CryptoConnect()73   void CryptoConnect() { crypto_stream_->CryptoConnect(); }
74 
ShouldKeepConnectionAlive()75   bool ShouldKeepConnectionAlive() const override { return true; }
76 
GetMutableCryptoStream()77   QuicCryptoStream* GetMutableCryptoStream() override {
78     return crypto_stream_.get();
79   }
GetCryptoStream()80   const QuicCryptoStream* GetCryptoStream() const override {
81     return crypto_stream_.get();
82   }
83 
84   // Returns true once the encryption has been established and the client
85   // indication has been sent.  No application data will be read or written
86   // before the connection is ready.  Once the connection becomes ready, this
87   // method will never return false.
IsSessionReady()88   bool IsSessionReady() const override { return ready_; }
89 
90   QuicStream* CreateIncomingStream(QuicStreamId id) override;
CreateIncomingStream(PendingStream *)91   QuicStream* CreateIncomingStream(PendingStream* /*pending*/) override {
92     QUIC_BUG << "QuicTransportClientSession::CreateIncomingStream("
93                 "PendingStream) not implemented";
94     return nullptr;
95   }
96 
97   void SetDefaultEncryptionLevel(EncryptionLevel level) override;
98   void OnOneRttKeysAvailable() override;
99   void OnMessageReceived(quiche::QuicheStringPiece message) override;
100 
101   // Return the earliest incoming stream that has been received by the session
102   // but has not been accepted.  Returns nullptr if there are no incoming
103   // streams.
104   QuicTransportStream* AcceptIncomingBidirectionalStream();
105   QuicTransportStream* AcceptIncomingUnidirectionalStream();
106 
107   using QuicSession::CanOpenNextOutgoingBidirectionalStream;
108   using QuicSession::CanOpenNextOutgoingUnidirectionalStream;
109   QuicTransportStream* OpenOutgoingBidirectionalStream();
110   QuicTransportStream* OpenOutgoingUnidirectionalStream();
111 
112   using QuicSession::datagram_queue;
113 
114  protected:
115   class QUIC_EXPORT_PRIVATE ClientIndication : public QuicStream {
116    public:
117     using QuicStream::QuicStream;
118 
119     // This method should never be called, since the stream is client-initiated
120     // unidirectional.
OnDataAvailable()121     void OnDataAvailable() override {
122       QUIC_BUG << "Received data on a write-only stream";
123     }
124   };
125 
126   // Creates and activates a QuicTransportStream for the given ID.
127   QuicTransportStream* CreateStream(QuicStreamId id);
128 
129   // Serializes the client indication as described in
130   // https://vasilvv.github.io/webtransport/draft-vvv-webtransport-quic.html#rfc.section.3.2
131   std::string SerializeClientIndication();
132   // Creates the client indication stream and sends the client indication on it.
133   void SendClientIndication();
134 
135   void OnCanCreateNewOutgoingStream(bool unidirectional) override;
136 
137   std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
138   GURL url_;
139   url::Origin origin_;
140   ClientVisitor* visitor_;  // not owned
141   bool client_indication_sent_ = false;
142   bool alpn_received_ = false;
143   bool ready_ = false;
144 
145   // Contains all of the streams that has been received by the session but have
146   // not been processed by the application.
147   // TODO(vasilvv): currently, we always send MAX_STREAMS as long as the overall
148   // maximum number of streams for the connection has not been exceeded. We
149   // should also limit the maximum number of streams that the consuming code
150   // has not accepted to a smaller number, by checking the size of
151   // |incoming_bidirectional_streams_| and |incoming_unidirectional_streams_|
152   // before sending MAX_STREAMS.
153   QuicCircularDeque<QuicTransportStream*> incoming_bidirectional_streams_;
154   QuicCircularDeque<QuicTransportStream*> incoming_unidirectional_streams_;
155 };
156 
157 }  // namespace quic
158 
159 #endif  // QUICHE_QUIC_QUIC_TRANSPORT_QUIC_TRANSPORT_SESSION_H_
160