summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/core/quic_session.h
blob: d06e1fe43a462cbd914adfc19a21b2d28ffd1df6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// A QuicSession, which demuxes a single connection to individual streams.

#ifndef QUICHE_QUIC_CORE_QUIC_SESSION_H_
#define QUICHE_QUIC_CORE_QUIC_SESSION_H_

#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
#include "quic/core/crypto/tls_connection.h"
#include "quic/core/frames/quic_ack_frequency_frame.h"
#include "quic/core/frames/quic_stop_sending_frame.h"
#include "quic/core/frames/quic_window_update_frame.h"
#include "quic/core/handshaker_delegate_interface.h"
#include "quic/core/legacy_quic_stream_id_manager.h"
#include "quic/core/proto/cached_network_parameters_proto.h"
#include "quic/core/quic_connection.h"
#include "quic/core/quic_control_frame_manager.h"
#include "quic/core/quic_crypto_stream.h"
#include "quic/core/quic_datagram_queue.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_packet_creator.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_path_validator.h"
#include "quic/core/quic_stream.h"
#include "quic/core/quic_stream_frame_data_producer.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_write_blocked_list.h"
#include "quic/core/session_notifier_interface.h"
#include "quic/core/stream_delegate_interface.h"
#include "quic/core/uber_quic_stream_id_manager.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_mem_slice.h"
#include "quic/platform/api/quic_socket_address.h"
#include "common/quiche_linked_hash_map.h"

namespace quic {

class QuicCryptoStream;
class QuicFlowController;
class QuicStream;
class QuicStreamIdManager;

namespace test {
class QuicSessionPeer;
}  // namespace test

class QUIC_EXPORT_PRIVATE QuicSession
    : public QuicConnectionVisitorInterface,
      public SessionNotifierInterface,
      public QuicStreamFrameDataProducer,
      public QuicStreamIdManager::DelegateInterface,
      public HandshakerDelegateInterface,
      public StreamDelegateInterface,
      public QuicControlFrameManager::DelegateInterface {
 public:
  // An interface from the session to the entity owning the session.
  // This lets the session notify its owner (the Dispatcher) when the connection
  // is closed, blocked, or added/removed from the time-wait list.
  class QUIC_EXPORT_PRIVATE Visitor {
   public:
    virtual ~Visitor() {}

    // Called when the connection is closed after the streams have been closed.
    virtual void OnConnectionClosed(QuicConnectionId server_connection_id,
                                    QuicErrorCode error,
                                    const std::string& error_details,
                                    ConnectionCloseSource source) = 0;

    // Called when the session has become write blocked.
    virtual void OnWriteBlocked(QuicBlockedWriterInterface* blocked_writer) = 0;

    // Called when the session receives reset on a stream from the peer.
    virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) = 0;

    // Called when the session receives a STOP_SENDING for a stream from the
    // peer.
    virtual void OnStopSendingReceived(const QuicStopSendingFrame& frame) = 0;

    // Called when a NewConnectionId frame has been sent.
    virtual void OnNewConnectionIdSent(
        const QuicConnectionId& server_connection_id,
        const QuicConnectionId& new_connection_id) = 0;

    // Called when a ConnectionId has been retired.
    virtual void OnConnectionIdRetired(
        const QuicConnectionId& server_connection_id) = 0;
  };

  // Does not take ownership of |connection| or |visitor|.
  QuicSession(QuicConnection* connection, Visitor* owner,
              const QuicConfig& config,
              const ParsedQuicVersionVector& supported_versions,
              QuicStreamCount num_expected_unidirectional_static_streams);
  QuicSession(QuicConnection* connection, Visitor* owner,
              const QuicConfig& config,
              const ParsedQuicVersionVector& supported_versions,
              QuicStreamCount num_expected_unidirectional_static_streams,
              std::unique_ptr<QuicDatagramQueue::Observer> datagram_observer);
  QuicSession(const QuicSession&) = delete;
  QuicSession& operator=(const QuicSession&) = delete;

  ~QuicSession() override;

  virtual void Initialize();

  // Return the reserved crypto stream as a constant pointer.
  virtual const QuicCryptoStream* GetCryptoStream() const = 0;

  // QuicConnectionVisitorInterface methods:
  void OnStreamFrame(const QuicStreamFrame& frame) override;
  void OnCryptoFrame(const QuicCryptoFrame& frame) override;
  void OnRstStream(const QuicRstStreamFrame& frame) override;
  void OnGoAway(const QuicGoAwayFrame& frame) override;
  void OnMessageReceived(absl::string_view message) override;
  void OnHandshakeDoneReceived() override;
  void OnNewTokenReceived(absl::string_view token) override;
  void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
  void OnBlockedFrame(const QuicBlockedFrame& frame) override;
  void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
                          ConnectionCloseSource source) override;
  void OnWriteBlocked() override;
  void OnSuccessfulVersionNegotiation(
      const ParsedQuicVersion& version) override;
  void OnPacketReceived(const QuicSocketAddress& self_address,
                        const QuicSocketAddress& peer_address,
                        bool is_connectivity_probe) override;
  void OnCanWrite() override;
  bool SendProbingData() override;
  bool ValidateStatelessReset(
      const quic::QuicSocketAddress& /*self_address*/,
      const quic::QuicSocketAddress& /*peer_address*/) override {
    return true;
  }
  void OnCongestionWindowChange(QuicTime /*now*/) override {}
  void OnConnectionMigration(AddressChangeType /*type*/) override {}
  // Adds a connection level WINDOW_UPDATE frame.
  void OnAckNeedsRetransmittableFrame() override;
  void SendAckFrequency(const QuicAckFrequencyFrame& frame) override;
  void SendNewConnectionId(const QuicNewConnectionIdFrame& frame) override;
  void SendRetireConnectionId(uint64_t sequence_number) override;
  void OnServerConnectionIdIssued(
      const QuicConnectionId& server_connection_id) override;
  void OnServerConnectionIdRetired(
      const QuicConnectionId& server_connection_id) override;
  bool WillingAndAbleToWrite() const override;
  std::string GetStreamsInfoForLogging() const override;
  void OnPathDegrading() override;
  void OnForwardProgressMadeAfterPathDegrading() override;
  bool AllowSelfAddressChange() const override;
  HandshakeState GetHandshakeState() const override;
  bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
  bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
  void OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
  void OnPacketDecrypted(EncryptionLevel level) override;
  void OnOneRttPacketAcknowledged() override;
  void OnHandshakePacketSent() override;
  void OnKeyUpdate(KeyUpdateReason /*reason*/) override {}
  std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
      override;
  std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
  void BeforeConnectionCloseSent() override {}
  bool ValidateToken(absl::string_view token) override;
  bool MaybeSendAddressToken() override;
  bool IsKnownServerAddress(
      const QuicSocketAddress& /*address*/) const override {
    return false;
  }

  // QuicStreamFrameDataProducer
  WriteStreamDataResult WriteStreamData(QuicStreamId id,
                                        QuicStreamOffset offset,
                                        QuicByteCount data_length,
                                        QuicDataWriter* writer) override;
  bool WriteCryptoData(EncryptionLevel level, QuicStreamOffset offset,
                       QuicByteCount data_length,
                       QuicDataWriter* writer) override;

  // SessionNotifierInterface methods:
  bool OnFrameAcked(const QuicFrame& frame, QuicTime::Delta ack_delay_time,
                    QuicTime receive_timestamp) override;
  void OnStreamFrameRetransmitted(const QuicStreamFrame& frame) override;
  void OnFrameLost(const QuicFrame& frame) override;
  void RetransmitFrames(const QuicFrames& frames,
                        TransmissionType type) override;
  bool IsFrameOutstanding(const QuicFrame& frame) const override;
  bool HasUnackedCryptoData() const override;
  bool HasUnackedStreamData() const override;

  void SendMaxStreams(QuicStreamCount stream_count,
                      bool unidirectional) override;
  // The default implementation does nothing. Subclasses should override if
  // for example they queue up stream requests.
  virtual void OnCanCreateNewOutgoingStream(bool /*unidirectional*/) {}

  // Called on every incoming packet. Passes |packet| through to |connection_|.
  virtual void ProcessUdpPacket(const QuicSocketAddress& self_address,
                                const QuicSocketAddress& peer_address,
                                const QuicReceivedPacket& packet);

  // Sends |message| as a QUIC DATAGRAM frame (QUIC MESSAGE frame in gQUIC).
  // See <https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram> for
  // more details.
  //
  // Returns a MessageResult struct which includes the status of the write
  // operation and a message ID.  The message ID (not sent on the wire) can be
  // used to track the message; OnMessageAcked and OnMessageLost are called when
  // a specific message gets acked or lost.
  //
  // If the write operation is successful, all of the slices in |message| are
  // consumed, leaving them empty.  If MESSAGE_STATUS_INTERNAL_ERROR is
  // returned, the slices in question may or may not be consumed; it is no
  // longer safe to access those.  For all other status codes, |message| is kept
  // intact.
  //
  // Note that SendMessage will fail with status = MESSAGE_STATUS_BLOCKED
  // if the connection is congestion control blocked or the underlying socket is
  // write blocked. In this case the caller can retry sending message again when
  // connection becomes available, for example after getting OnCanWrite()
  // callback.
  //
  // SendMessage flushes the current packet even it is not full; if the
  // application needs to bundle other data in the same packet, consider using
  // QuicConnection::ScopedPacketFlusher around the relevant write operations.
  MessageResult SendMessage(absl::Span<QuicMemSlice> message);

  // Same as above SendMessage, except caller can specify if the given |message|
  // should be flushed even if the underlying connection is deemed unwritable.
  MessageResult SendMessage(absl::Span<QuicMemSlice> message, bool flush);

  // Single-slice version of SendMessage().  Unlike the version above, this
  // version always takes ownership of the slice.
  MessageResult SendMessage(QuicMemSlice message);

  // Called when message with |message_id| gets acked.
  virtual void OnMessageAcked(QuicMessageId message_id,
                              QuicTime receive_timestamp);

  // Called when message with |message_id| is considered as lost.
  virtual void OnMessageLost(QuicMessageId message_id);

  // QuicControlFrameManager::DelegateInterface
  // Close the connection on error.
  void OnControlFrameManagerError(QuicErrorCode error_code,
                                  std::string error_details) override;
  // Called by control frame manager when it wants to write control frames to
  // the peer. Returns true if |frame| is consumed, false otherwise. The frame
  // will be sent in specified transmission |type|.
  bool WriteControlFrame(const QuicFrame& frame,
                         TransmissionType type) override;

  // Called to send RST_STREAM (and STOP_SENDING) and close stream. If stream
  // |id| does not exist, just send RST_STREAM (and STOP_SENDING).
  virtual void ResetStream(QuicStreamId id, QuicRstStreamErrorCode error);

  // Called when the session wants to go away and not accept any new streams.
  virtual void SendGoAway(QuicErrorCode error_code, const std::string& reason);

  // Sends a BLOCKED frame.
  virtual void SendBlocked(QuicStreamId id);

  // Sends a WINDOW_UPDATE frame.
  virtual void SendWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset);

  // Called by stream |stream_id| when it gets closed.
  virtual void OnStreamClosed(QuicStreamId stream_id);

  // Returns true if outgoing packets will be encrypted, even if the server
  // hasn't confirmed the handshake yet.
  virtual bool IsEncryptionEstablished() const;

  // Returns true if 1RTT keys are available.
  bool OneRttKeysAvailable() const;

  // Called by the QuicCryptoStream when a new QuicConfig has been negotiated.
  virtual void OnConfigNegotiated();

  // Called by the TLS handshaker when ALPS data is received.
  // Returns an error message if an error has occurred, or nullopt otherwise.
  virtual absl::optional<std::string> OnAlpsData(const uint8_t* alps_data,
                                                 size_t alps_length);

  // From HandshakerDelegateInterface
  bool OnNewDecryptionKeyAvailable(EncryptionLevel level,
                                   std::unique_ptr<QuicDecrypter> decrypter,
                                   bool set_alternative_decrypter,
                                   bool latch_once_used) override;
  void OnNewEncryptionKeyAvailable(
      EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) override;
  void SetDefaultEncryptionLevel(EncryptionLevel level) override;
  void OnTlsHandshakeComplete() override;
  void DiscardOldDecryptionKey(EncryptionLevel level) override;
  void DiscardOldEncryptionKey(EncryptionLevel level) override;
  void NeuterUnencryptedData() override;
  void NeuterHandshakeData() override;
  void OnZeroRttRejected(int reason) override;
  bool FillTransportParameters(TransportParameters* params) override;
  QuicErrorCode ProcessTransportParameters(const TransportParameters& params,
                                           bool is_resumption,
                                           std::string* error_details) override;
  void OnHandshakeCallbackDone() override;
  bool PacketFlusherAttached() const override;

  // Implement StreamDelegateInterface.
  void OnStreamError(QuicErrorCode error_code,
                     std::string error_details) override;
  void OnStreamError(QuicErrorCode error_code,
                     QuicIetfTransportErrorCodes ietf_error,
                     std::string error_details) override;
  // Sets priority in the write blocked list.
  void RegisterStreamPriority(
      QuicStreamId id, bool is_static,
      const spdy::SpdyStreamPrecedence& precedence) override;
  // Clears priority from the write blocked list.
  void UnregisterStreamPriority(QuicStreamId id, bool is_static) override;
  // Updates priority on the write blocked list.
  void UpdateStreamPriority(
      QuicStreamId id,
      const spdy::SpdyStreamPrecedence& new_precedence) override;

  // Called by streams when they want to write data to the peer.
  // Returns a pair with the number of bytes consumed from data, and a boolean
  // indicating if the fin bit was consumed.  This does not indicate the data
  // has been sent on the wire: it may have been turned into a packet and queued
  // if the socket was unexpectedly blocked.
  QuicConsumedData WritevData(QuicStreamId id, size_t write_length,
                              QuicStreamOffset offset, StreamSendingState state,
                              TransmissionType type,
                              EncryptionLevel level) override;

  size_t SendCryptoData(EncryptionLevel level, size_t write_length,
                        QuicStreamOffset offset,
                        TransmissionType type) override;

  // Called by the QuicCryptoStream when a handshake message is sent.
  virtual void OnCryptoHandshakeMessageSent(
      const CryptoHandshakeMessage& message);

  // Called by the QuicCryptoStream when a handshake message is received.
  virtual void OnCryptoHandshakeMessageReceived(
      const CryptoHandshakeMessage& message);

  // Returns mutable config for this session. Returned config is owned
  // by QuicSession.
  QuicConfig* config();

  // Returns true if the stream existed previously and has been closed.
  // Returns false if the stream is still active or if the stream has
  // not yet been created.
  bool IsClosedStream(QuicStreamId id);

  QuicConnection* connection() { return connection_; }
  const QuicConnection* connection() const { return connection_; }
  const QuicSocketAddress& peer_address() const {
    return connection_->peer_address();
  }
  const QuicSocketAddress& self_address() const {
    return connection_->self_address();
  }
  QuicConnectionId connection_id() const {
    return connection_->connection_id();
  }

  // Returns the number of currently open streams, excluding static streams, and
  // never counting unfinished streams.
  size_t GetNumActiveStreams() const;

  // Add the stream to the session's write-blocked list because it is blocked by
  // connection-level flow control but not by its own stream-level flow control.
  // The stream will be given a chance to write when a connection-level
  // WINDOW_UPDATE arrives.
  virtual void MarkConnectionLevelWriteBlocked(QuicStreamId id);

  // Called to close zombie stream |id|.
  void MaybeCloseZombieStream(QuicStreamId id);

  // Returns true if there is pending handshake data in the crypto stream.
  // TODO(ianswett): Make this private or remove.
  bool HasPendingHandshake() const;

  // Returns true if the session has data to be sent, either queued in the
  // connection, or in a write-blocked stream.
  bool HasDataToWrite() const;

  // Initiates a path validation on the path described in the given context,
  // asynchronously calls |result_delegate| upon success or failure.
  // The initiator should extend QuicPathValidationContext to provide the writer
  // and ResultDelegate to react upon the validation result.
  // Example implementations of these for path validation for connection
  // migration could be:
  //  class QUIC_EXPORT_PRIVATE PathMigrationContext
  //      : public QuicPathValidationContext {
  //   public:
  //    PathMigrationContext(std::unique_ptr<QuicPacketWriter> writer,
  //                         const QuicSocketAddress& self_address,
  //                         const QuicSocketAddress& peer_address)
  //        : QuicPathValidationContext(self_address, peer_address),
  //          alternative_writer_(std::move(writer)) {}
  //
  //    QuicPacketWriter* WriterToUse() override {
  //         return alternative_writer_.get();
  //    }
  //
  //    QuicPacketWriter* ReleaseWriter() {
  //         return alternative_writer_.release();
  //    }
  //
  //   private:
  //    std::unique_ptr<QuicPacketWriter> alternative_writer_;
  //  };
  //
  //  class PathMigrationValidationResultDelegate
  //      : public QuicPathValidator::ResultDelegate {
  //   public:
  //    PathMigrationValidationResultDelegate(QuicConnection* connection)
  //        : QuicPathValidator::ResultDelegate(), connection_(connection) {}
  //
  //    void OnPathValidationSuccess(
  //        std::unique_ptr<QuicPathValidationContext> context) override {
  //    // Do some work to prepare for migration.
  //    // ...
  //
  //    // Actually migrate to the validated path.
  //    auto migration_context = std::unique_ptr<PathMigrationContext>(
  //        static_cast<PathMigrationContext*>(context.release()));
  //    connection_->MigratePath(migration_context->self_address(),
  //                          migration_context->peer_address(),
  //                          migration_context->ReleaseWriter(),
  //                          /*owns_writer=*/true);
  //
  //    // Post-migration actions
  //    // ...
  //  }
  //
  //    void OnPathValidationFailure(
  //        std::unique_ptr<QuicPathValidationContext> /*context*/) override {
  //    // Handle validation failure.
  //  }
  //
  //   private:
  //    QuicConnection* connection_;
  //  };
  void ValidatePath(
      std::unique_ptr<QuicPathValidationContext> context,
      std::unique_ptr<QuicPathValidator::ResultDelegate> result_delegate);

  // Return true if there is a path being validated.
  bool HasPendingPathValidation() const;

  // Switch to the path described in |context| without validating the path.
  bool MigratePath(const QuicSocketAddress& self_address,
                   const QuicSocketAddress& peer_address,
                   QuicPacketWriter* writer, bool owns_writer);

  // Returns the largest payload that will fit into a single MESSAGE frame.
  // Because overhead can vary during a connection, this method should be
  // checked for every message.
  QuicPacketLength GetCurrentLargestMessagePayload() const;

  // Returns the largest payload that will fit into a single MESSAGE frame at
  // any point during the connection.  This assumes the version and
  // connection ID lengths do not change.
  QuicPacketLength GetGuaranteedLargestMessagePayload() const;

  bool transport_goaway_sent() const { return transport_goaway_sent_; }

  bool transport_goaway_received() const { return transport_goaway_received_; }

  // Returns the Google QUIC error code
  QuicErrorCode error() const { return on_closed_frame_.quic_error_code; }
  const std::string& error_details() const {
    return on_closed_frame_.error_details;
  }
  uint64_t transport_close_frame_type() const {
    return on_closed_frame_.transport_close_frame_type;
  }
  QuicConnectionCloseType close_type() const {
    return on_closed_frame_.close_type;
  }

  Perspective perspective() const { return perspective_; }

  QuicFlowController* flow_controller() { return &flow_controller_; }

  // Returns true if connection is flow controller blocked.
  bool IsConnectionFlowControlBlocked() const;

  // Returns true if any stream is flow controller blocked.
  bool IsStreamFlowControlBlocked();

  size_t max_open_incoming_bidirectional_streams() const;
  size_t max_open_incoming_unidirectional_streams() const;

  size_t MaxAvailableBidirectionalStreams() const;
  size_t MaxAvailableUnidirectionalStreams() const;

  // Returns existing stream with id = |stream_id|. If no
  // such stream exists, and |stream_id| is a peer-created stream id,
  // then a new stream is created and returned. In all other cases, nullptr is
  // returned.
  // Caller does not own the returned stream.
  QuicStream* GetOrCreateStream(const QuicStreamId stream_id);

  // Mark a stream as draining.
  void StreamDraining(QuicStreamId id, bool unidirectional);

  // Returns true if this stream should yield writes to another blocked stream.
  virtual bool ShouldYield(QuicStreamId stream_id);

  // Clean up closed_streams_.
  void CleanUpClosedStreams();

  const ParsedQuicVersionVector& supported_versions() const {
    return supported_versions_;
  }

  QuicStreamId next_outgoing_bidirectional_stream_id() const;
  QuicStreamId next_outgoing_unidirectional_stream_id() const;

  // Return true if given stream is peer initiated.
  bool IsIncomingStream(QuicStreamId id) const;

  // Record errors when a connection is closed at the server side, should only
  // be called from server's perspective.
  // Noop if |error| is QUIC_NO_ERROR.
  static void RecordConnectionCloseAtServer(QuicErrorCode error,
                                            ConnectionCloseSource source);

  inline QuicTransportVersion transport_version() const {
    return connection_->transport_version();
  }

  inline ParsedQuicVersion version() const { return connection_->version(); }

  bool is_configured() const { return is_configured_; }

  // Called to neuter crypto data of encryption |level|.
  void NeuterCryptoDataOfEncryptionLevel(EncryptionLevel level);

  // Returns the ALPN values to negotiate on this session.
  virtual std::vector<std::string> GetAlpnsToOffer() const {
    // TODO(vasilvv): this currently sets HTTP/3 by default.  Switch all
    // non-HTTP applications to appropriate ALPNs.
    return std::vector<std::string>({AlpnForVersion(connection()->version())});
  }

  // Provided a list of ALPNs offered by the client, selects an ALPN from the
  // list, or alpns.end() if none of the ALPNs are acceptable.
  virtual std::vector<absl::string_view>::const_iterator SelectAlpn(
      const std::vector<absl::string_view>& alpns) const;

  // Called when the ALPN of the connection is established for a connection that
  // uses TLS handshake.
  virtual void OnAlpnSelected(absl::string_view alpn);

  // Called on clients by the crypto handshaker to provide application state
  // necessary for sending application data in 0-RTT. The state provided here is
  // the same state that was provided to the crypto handshaker in
  // QuicCryptoStream::SetServerApplicationStateForResumption on a previous
  // connection. Application protocols that require state to be carried over
  // from the previous connection to support 0-RTT data must implement this
  // method to ingest this state. For example, an HTTP/3 QuicSession would
  // implement this function to process the remembered server SETTINGS and apply
  // those SETTINGS to 0-RTT data. This function returns true if the application
  // state has been successfully processed, and false if there was an error
  // processing the cached state and the connection should be closed.
  virtual bool ResumeApplicationState(ApplicationState* /*cached_state*/) {
    return true;
  }

  // Does actual work of sending RESET_STREAM, if the stream type allows.
  // Also informs the connection so that pending stream frames can be flushed.
  virtual void MaybeSendRstStreamFrame(QuicStreamId id,
                                       QuicResetStreamError error,
                                       QuicStreamOffset bytes_written);

  // Sends a STOP_SENDING frame if the stream type allows.
  virtual void MaybeSendStopSendingFrame(QuicStreamId id,
                                         QuicResetStreamError error);

  // Returns the encryption level to send application data.
  EncryptionLevel GetEncryptionLevelToSendApplicationData() const;

  const absl::optional<std::string> user_agent_id() const {
    return user_agent_id_;
  }

  // TODO(wub): remove saving user-agent to QuicSession.
  void SetUserAgentId(std::string user_agent_id) {
    user_agent_id_ = std::move(user_agent_id);
    connection()->OnUserAgentIdKnown(user_agent_id_.value());
  }

  void SetSourceAddressTokenToSend(absl::string_view token) {
    connection()->SetSourceAddressTokenToSend(token);
  }

  const QuicClock* GetClock() const {
    return connection()->helper()->GetClock();
  }

  bool liveness_testing_in_progress() const {
    return liveness_testing_in_progress_;
  }

  bool permutes_tls_extensions() const { return permutes_tls_extensions_; }

  virtual QuicSSLConfig GetSSLConfig() const { return QuicSSLConfig(); }

  // Latched value of flag --quic_tls_server_support_client_cert.
  bool support_client_cert() const { return support_client_cert_; }

  // Get latched flag value.
  bool add_cached_network_parameters_to_address_token() const {
    return add_cached_network_parameters_to_address_token_;
  }

  // Try converting all pending streams to normal streams.
  void ProcessAllPendingStreams();

  const ParsedQuicVersionVector& client_original_supported_versions() const {
    QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
    return client_original_supported_versions_;
  }
  void set_client_original_supported_versions(
      const ParsedQuicVersionVector& client_original_supported_versions) {
    QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
    client_original_supported_versions_ = client_original_supported_versions;
  }

 protected:
  using StreamMap =
      absl::flat_hash_map<QuicStreamId, std::unique_ptr<QuicStream>>;

  using PendingStreamMap =
      absl::flat_hash_map<QuicStreamId, std::unique_ptr<PendingStream>>;

  using ClosedStreams = std::vector<std::unique_ptr<QuicStream>>;

  using ZombieStreamMap =
      absl::flat_hash_map<QuicStreamId, std::unique_ptr<QuicStream>>;

  // Creates a new stream to handle a peer-initiated stream.
  // Caller does not own the returned stream.
  // Returns nullptr and does error handling if the stream can not be created.
  virtual QuicStream* CreateIncomingStream(QuicStreamId id) = 0;
  virtual QuicStream* CreateIncomingStream(PendingStream* pending) = 0;

  // Return the reserved crypto stream.
  virtual QuicCryptoStream* GetMutableCryptoStream() = 0;

  // Adds |stream| to the stream map.
  virtual void ActivateStream(std::unique_ptr<QuicStream> stream);

  // Set transmission type of next sending packets.
  void SetTransmissionType(TransmissionType type);

  // Returns the stream ID for a new outgoing bidirectional/unidirectional
  // stream, and increments the underlying counter.
  QuicStreamId GetNextOutgoingBidirectionalStreamId();
  QuicStreamId GetNextOutgoingUnidirectionalStreamId();

  // Indicates whether the next outgoing bidirectional/unidirectional stream ID
  // can be allocated or not. The test for version-99/IETF QUIC is whether it
  // will exceed the maximum-stream-id or not. For non-version-99 (Google) QUIC
  // it checks whether the next stream would exceed the limit on the number of
  // open streams.
  bool CanOpenNextOutgoingBidirectionalStream();
  bool CanOpenNextOutgoingUnidirectionalStream();

  // Returns the maximum bidirectional streams parameter sent with the handshake
  // as a transport parameter, or in the most recent MAX_STREAMS frame.
  QuicStreamCount GetAdvertisedMaxIncomingBidirectionalStreams() const;

  // When a stream is closed locally, it may not yet know how many bytes the
  // peer sent on that stream.
  // When this data arrives (via stream frame w. FIN, trailing headers, or RST)
  // this method is called, and correctly updates the connection level flow
  // controller.
  virtual void OnFinalByteOffsetReceived(QuicStreamId id,
                                         QuicStreamOffset final_byte_offset);

  // Returns true if a frame with the given type and id can be prcoessed by a
  // PendingStream. However, the frame will always be processed by a QuicStream
  // if one exists with the given stream_id.
  virtual bool UsesPendingStreamForFrame(QuicFrameType /*type*/,
                                         QuicStreamId /*stream_id*/) const {
    return false;
  }

  // Returns true if a pending stream should be converted to a real stream after
  // a corresponding STREAM_FRAME is received.
  virtual bool ShouldProcessPendingStreamImmediately() const { return true; }

  spdy::SpdyPriority GetSpdyPriorityofStream(QuicStreamId stream_id) const {
    return write_blocked_streams_.GetSpdyPriorityofStream(stream_id);
  }

  size_t pending_streams_size() const { return pending_stream_map_.size(); }

  ClosedStreams* closed_streams() { return &closed_streams_; }

  void set_largest_peer_created_stream_id(
      QuicStreamId largest_peer_created_stream_id);

  QuicWriteBlockedList* write_blocked_streams() {
    return &write_blocked_streams_;
  }

  // Returns true if the stream is still active.
  bool IsOpenStream(QuicStreamId id);

  // Returns true if the stream is a static stream.
  bool IsStaticStream(QuicStreamId id) const;

  // Close connection when receive a frame for a locally-created nonexistent
  // stream.
  // Prerequisite: IsClosedStream(stream_id) == false
  // Server session might need to override this method to allow server push
  // stream to be promised before creating an active stream.
  virtual void HandleFrameOnNonexistentOutgoingStream(QuicStreamId stream_id);

  virtual bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id);

  void InsertLocallyClosedStreamsHighestOffset(const QuicStreamId id,
                                               QuicStreamOffset offset);
  // If stream is a locally closed stream, this RST will update FIN offset.
  // Otherwise stream is a preserved stream and the behavior of it depends on
  // derived class's own implementation.
  virtual void HandleRstOnValidNonexistentStream(
      const QuicRstStreamFrame& frame);

  // Returns a stateless reset token which will be included in the public reset
  // packet.
  virtual StatelessResetToken GetStatelessResetToken() const;

  QuicControlFrameManager& control_frame_manager() {
    return control_frame_manager_;
  }

  const LegacyQuicStreamIdManager& stream_id_manager() const {
    return stream_id_manager_;
  }

  QuicDatagramQueue* datagram_queue() { return &datagram_queue_; }

  size_t num_static_streams() const { return num_static_streams_; }

  size_t num_zombie_streams() const { return num_zombie_streams_; }

  bool was_zero_rtt_rejected() const { return was_zero_rtt_rejected_; }

  size_t num_outgoing_draining_streams() const {
    return num_outgoing_draining_streams_;
  }

  size_t num_draining_streams() const { return num_draining_streams_; }

  // Processes the stream type information of |pending| depending on
  // different kinds of sessions' own rules. If the pending stream has been
  // converted to a normal stream, returns a pointer to the new stream;
  // otherwise, returns nullptr.
  virtual QuicStream* ProcessPendingStream(PendingStream* /*pending*/) {
    return nullptr;
  }

  // Called by applications to perform |action| on active streams.
  // Stream iteration will be stopped if action returns false.
  void PerformActionOnActiveStreams(std::function<bool(QuicStream*)> action);
  void PerformActionOnActiveStreams(
      std::function<bool(QuicStream*)> action) const;

  // Return the largest peer created stream id depending on directionality
  // indicated by |unidirectional|.
  QuicStreamId GetLargestPeerCreatedStreamId(bool unidirectional) const;

  // Deletes the connection and sets it to nullptr, so calling it mulitiple
  // times is safe.
  void DeleteConnection();

  // Call SetPriority() on stream id |id| and return true if stream is active.
  bool MaybeSetStreamPriority(QuicStreamId stream_id,
                              const spdy::SpdyStreamPrecedence& precedence);

  void SetLossDetectionTuner(
      std::unique_ptr<LossDetectionTunerInterface> tuner) {
    connection()->SetLossDetectionTuner(std::move(tuner));
  }

  // Find stream with |id|, returns nullptr if the stream does not exist or
  // closed. static streams and zombie streams are not considered active
  // streams.
  QuicStream* GetActiveStream(QuicStreamId id) const;

  const UberQuicStreamIdManager& ietf_streamid_manager() const {
    QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version()));
    return ietf_streamid_manager_;
  }

  // Only called at a server session. Generate a CachedNetworkParameters that
  // can be sent to the client as part of the address token, based on the latest
  // bandwidth/rtt information. If return absl::nullopt, address token will not
  // contain the CachedNetworkParameters.
  virtual absl::optional<CachedNetworkParameters>
  GenerateCachedNetworkParameters() const {
    return absl::nullopt;
  }

 private:
  friend class test::QuicSessionPeer;

  // Called in OnConfigNegotiated when we receive a new stream level flow
  // control window in a negotiated config. Closes the connection if invalid.
  void OnNewStreamFlowControlWindow(QuicStreamOffset new_window);

  // Called in OnConfigNegotiated when we receive a new unidirectional stream
  // flow control window in a negotiated config.
  void OnNewStreamUnidirectionalFlowControlWindow(QuicStreamOffset new_window);

  // Called in OnConfigNegotiated when we receive a new outgoing bidirectional
  // stream flow control window in a negotiated config.
  void OnNewStreamOutgoingBidirectionalFlowControlWindow(
      QuicStreamOffset new_window);

  // Called in OnConfigNegotiated when we receive a new incoming bidirectional
  // stream flow control window in a negotiated config.
  void OnNewStreamIncomingBidirectionalFlowControlWindow(
      QuicStreamOffset new_window);

  // Called in OnConfigNegotiated when we receive a new connection level flow
  // control window in a negotiated config. Closes the connection if invalid.
  void OnNewSessionFlowControlWindow(QuicStreamOffset new_window);

  // Debug helper for |OnCanWrite()|, check that OnStreamWrite() makes
  // forward progress.  Returns false if busy loop detected.
  bool CheckStreamNotBusyLooping(QuicStream* stream,
                                 uint64_t previous_bytes_written,
                                 bool previous_fin_sent);

  // Debug helper for OnCanWrite. Check that after QuicStream::OnCanWrite(),
  // if stream has buffered data and is not stream level flow control blocked,
  // it has to be in the write blocked list.
  bool CheckStreamWriteBlocked(QuicStream* stream) const;

  // Called in OnConfigNegotiated for Finch trials to measure performance of
  // starting with larger flow control receive windows.
  void AdjustInitialFlowControlWindows(size_t stream_window);

  // Find stream with |id|, returns nullptr if the stream does not exist or
  // closed.
  QuicStream* GetStream(QuicStreamId id) const;

  // Can return NULL, e.g., if the stream has been closed before.
  PendingStream* GetOrCreatePendingStream(QuicStreamId stream_id);

  // Let streams and control frame managers retransmit lost data, returns true
  // if all lost data is retransmitted. Returns false otherwise.
  bool RetransmitLostData();

  // Returns true if stream data should be written.
  bool CanWriteStreamData() const;

  // Closes the pending stream |stream_id| before it has been created.
  void ClosePendingStream(QuicStreamId stream_id);

  // Whether the frame with given type and id should be feed to a pending
  // stream.
  bool ShouldProcessFrameByPendingStream(QuicFrameType type,
                                         QuicStreamId id) const;

  // Process the pending stream if possible.
  void MaybeProcessPendingStream(PendingStream* pending);

  // Creates or gets pending stream, feeds it with |frame|, and returns the
  // pending stream. Can return NULL, e.g., if the stream ID is invalid.
  PendingStream* PendingStreamOnStreamFrame(const QuicStreamFrame& frame);

  // Creates or gets pending strea, feed it with |frame|, and closes the pending
  // stream.
  void PendingStreamOnRstStream(const QuicRstStreamFrame& frame);

  // Creates or gets pending stream, feeds it with |frame|, and records the
  // max_data in the pending stream.
  void PendingStreamOnWindowUpdateFrame(const QuicWindowUpdateFrame& frame);

  // Creates or gets pending stream, feeds it with |frame|, and records the
  // ietf_error_code in the pending stream.
  void PendingStreamOnStopSendingFrame(const QuicStopSendingFrame& frame);

  // Keep track of highest received byte offset of locally closed streams, while
  // waiting for a definitive final highest offset from the peer.
  absl::flat_hash_map<QuicStreamId, QuicStreamOffset>
      locally_closed_streams_highest_offset_;

  QuicConnection* connection_;

  // Store perspective on QuicSession during the constructor as it may be needed
  // during our destructor when connection_ may have already been destroyed.
  Perspective perspective_;

  // May be null.
  Visitor* visitor_;

  // A list of streams which need to write more data.  Stream register
  // themselves in their constructor, and unregisterm themselves in their
  // destructors, so the write blocked list must outlive all streams.
  QuicWriteBlockedList write_blocked_streams_;

  ClosedStreams closed_streams_;

  QuicConfig config_;

  // Map from StreamId to pointers to streams. Owns the streams.
  StreamMap stream_map_;

  // Map from StreamId to PendingStreams for peer-created unidirectional streams
  // which are waiting for the first byte of payload to arrive.
  PendingStreamMap pending_stream_map_;

  // TODO(fayang): Consider moving LegacyQuicStreamIdManager into
  // UberQuicStreamIdManager.
  // Manages stream IDs for Google QUIC.
  LegacyQuicStreamIdManager stream_id_manager_;

  // Manages stream IDs for version99/IETF QUIC
  UberQuicStreamIdManager ietf_streamid_manager_;

  // A counter for streams which have sent and received FIN but waiting for
  // application to consume data.
  size_t num_draining_streams_;

  // A counter for self initiated streams which have sent and received FIN but
  // waiting for application to consume data.
  size_t num_outgoing_draining_streams_;

  // A counter for static streams which are in stream_map_.
  size_t num_static_streams_;

  // A counter for streams which have done reading and writing, but are waiting
  // for acks.
  size_t num_zombie_streams_;

  // Received information for a connection close.
  QuicConnectionCloseFrame on_closed_frame_;

  // Used for connection-level flow control.
  QuicFlowController flow_controller_;

  // The stream id which was last popped in OnCanWrite, or 0, if not under the
  // call stack of OnCanWrite.
  QuicStreamId currently_writing_stream_id_;

  // Whether a transport layer GOAWAY frame has been sent.
  // Such a frame only exists in Google QUIC, therefore |transport_goaway_sent_|
  // is always false when using IETF QUIC.
  bool transport_goaway_sent_;

  // Whether a transport layer GOAWAY frame has been received.
  // Such a frame only exists in Google QUIC, therefore
  // |transport_goaway_received_| is always false when using IETF QUIC.
  bool transport_goaway_received_;

  QuicControlFrameManager control_frame_manager_;

  // Id of latest successfully sent message.
  QuicMessageId last_message_id_;

  // The buffer used to queue the DATAGRAM frames.
  QuicDatagramQueue datagram_queue_;

  // TODO(fayang): switch to linked_hash_set when chromium supports it. The bool
  // is not used here.
  // List of streams with pending retransmissions.
  quiche::QuicheLinkedHashMap<QuicStreamId, bool>
      streams_with_pending_retransmission_;

  // Clean up closed_streams_ when this alarm fires.
  std::unique_ptr<QuicAlarm> closed_streams_clean_up_alarm_;

  // Supported version list used by the crypto handshake only. Please note, this
  // list may be a superset of the connection framer's supported versions.
  ParsedQuicVersionVector supported_versions_;

  // Only non-empty on the client after receiving a version negotiation packet,
  // contains the configured versions from the original session before version
  // negotiation was received.
  ParsedQuicVersionVector client_original_supported_versions_;

  absl::optional<std::string> user_agent_id_;

  // Initialized to false. Set to true when the session has been properly
  // configured and is ready for general operation.
  bool is_configured_;

  // Whether the session has received a 0-RTT rejection (QUIC+TLS only).
  bool was_zero_rtt_rejected_;

  // This indicates a liveness testing is in progress, and push back the
  // creation of new outgoing bidirectional streams.
  bool liveness_testing_in_progress_;

  const bool add_cached_network_parameters_to_address_token_ =
      GetQuicReloadableFlag(
          quic_add_cached_network_parameters_to_address_token2);

  // Whether BoringSSL randomizes the order of TLS extensions.
  bool permutes_tls_extensions_ = true;

  const bool support_client_cert_ =
      GetQuicRestartFlag(quic_tls_server_support_client_cert);
};

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_QUIC_SESSION_H_