summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager.h
blob: 501310b1ee867d76a5b37f2aad49e71332ffb32b (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
// 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.

// QuicPeerIssuedConnectionIdManager handles the states associated with receving
// and retiring peer issued connection Ids.
// QuicSelfIssuedConnectionIdManager handles the states associated with
// connection Ids issued by the current end point.

#ifndef QUICHE_QUIC_CORE_QUIC_CONNECTION_ID_MANAGER_H_
#define QUICHE_QUIC_CORE_QUIC_CONNECTION_ID_MANAGER_H_

#include <cstddef>
#include <memory>

#include "absl/types/optional.h"
#include "quiche/quic/core/frames/quic_new_connection_id_frame.h"
#include "quiche/quic/core/frames/quic_retire_connection_id_frame.h"
#include "quiche/quic/core/quic_alarm.h"
#include "quiche/quic/core/quic_alarm_factory.h"
#include "quiche/quic/core/quic_clock.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/core/quic_interval_set.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/platform/api/quic_export.h"

namespace quic {

namespace test {
class QuicConnectionIdManagerPeer;
}  // namespace test

struct QUIC_EXPORT_PRIVATE QuicConnectionIdData {
  QuicConnectionIdData(const QuicConnectionId& connection_id,
                       uint64_t sequence_number,
                       const StatelessResetToken& stateless_reset_token);

  QuicConnectionId connection_id;
  uint64_t sequence_number;
  StatelessResetToken stateless_reset_token;
};

// Used by QuicSelfIssuedConnectionIdManager
// and QuicPeerIssuedConnectionIdManager.
class QUIC_EXPORT_PRIVATE QuicConnectionIdManagerVisitorInterface {
 public:
  virtual ~QuicConnectionIdManagerVisitorInterface() = default;
  virtual void OnPeerIssuedConnectionIdRetired() = 0;
  virtual bool SendNewConnectionId(const QuicNewConnectionIdFrame& frame) = 0;
  virtual void OnNewConnectionIdIssued(
      const QuicConnectionId& connection_id) = 0;
  virtual void OnSelfIssuedConnectionIdRetired(
      const QuicConnectionId& connection_id) = 0;
};

class QUIC_EXPORT_PRIVATE QuicPeerIssuedConnectionIdManager {
 public:
  // QuicPeerIssuedConnectionIdManager should be instantiated only when a peer
  // issued-non empty connection ID is received.
  QuicPeerIssuedConnectionIdManager(
      size_t active_connection_id_limit,
      const QuicConnectionId& initial_peer_issued_connection_id,
      const QuicClock* clock, QuicAlarmFactory* alarm_factory,
      QuicConnectionIdManagerVisitorInterface* visitor,
      QuicConnectionContext* context);

  ~QuicPeerIssuedConnectionIdManager();

  QuicErrorCode OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame,
                                       std::string* error_detail);

  bool HasUnusedConnectionId() const {
    return !unused_connection_id_data_.empty();
  }

  // Returns the data associated with an unused connection Id. After the call,
  // the Id is marked as used. Returns nullptr if there is no unused connection
  // Id.
  const QuicConnectionIdData* ConsumeOneUnusedConnectionId();

  // Add each active connection Id that is no longer on path to the pending
  // retirement connection Id list.
  void MaybeRetireUnusedConnectionIds(
      const std::vector<QuicConnectionId>& active_connection_ids_on_path);

  bool IsConnectionIdActive(const QuicConnectionId& cid) const;

  // Get the sequence numbers of all the connection Ids pending retirement when
  // it is safe to retires these Ids.
  std::vector<uint64_t> ConsumeToBeRetiredConnectionIdSequenceNumbers();

  // If old_connection_id is still tracked by QuicPeerIssuedConnectionIdManager,
  // replace it with new_connection_id. Otherwise, this is a no-op.
  void ReplaceConnectionId(const QuicConnectionId& old_connection_id,
                           const QuicConnectionId& new_connection_id);

 private:
  friend class test::QuicConnectionIdManagerPeer;

  // Add the connection Id to the pending retirement connection Id list and
  // schedule an alarm if needed.
  void PrepareToRetireActiveConnectionId(const QuicConnectionId& cid);

  bool IsConnectionIdNew(const QuicNewConnectionIdFrame& frame);

  void PrepareToRetireConnectionIdPriorTo(
      uint64_t retire_prior_to,
      std::vector<QuicConnectionIdData>* cid_data_vector);

  size_t active_connection_id_limit_;
  const QuicClock* clock_;
  std::unique_ptr<QuicAlarm> retire_connection_id_alarm_;
  std::vector<QuicConnectionIdData> active_connection_id_data_;
  std::vector<QuicConnectionIdData> unused_connection_id_data_;
  std::vector<QuicConnectionIdData> to_be_retired_connection_id_data_;
  // Track sequence numbers of recent NEW_CONNECTION_ID frames received from
  // the peer.
  QuicIntervalSet<uint64_t> recent_new_connection_id_sequence_numbers_;
  uint64_t max_new_connection_id_frame_retire_prior_to_ = 0u;
};

class QUIC_EXPORT_PRIVATE QuicSelfIssuedConnectionIdManager {
 public:
  QuicSelfIssuedConnectionIdManager(
      size_t active_connection_id_limit,
      const QuicConnectionId& initial_connection_id, const QuicClock* clock,
      QuicAlarmFactory* alarm_factory,
      QuicConnectionIdManagerVisitorInterface* visitor,
      QuicConnectionContext* context);

  virtual ~QuicSelfIssuedConnectionIdManager();

  QuicNewConnectionIdFrame IssueNewConnectionIdForPreferredAddress();

  QuicErrorCode OnRetireConnectionIdFrame(
      const QuicRetireConnectionIdFrame& frame, QuicTime::Delta pto_delay,
      std::string* error_detail);

  std::vector<QuicConnectionId> GetUnretiredConnectionIds() const;

  QuicConnectionId GetOneActiveConnectionId() const;

  // Called when the retire_connection_id alarm_ fires. Removes the to be
  // retired connection ID locally.
  void RetireConnectionId();

  // Sends new connection IDs if more can be sent.
  void MaybeSendNewConnectionIds();

  // The two functions are called on the client side to associate a client
  // connection ID with a new probing/migration path when client uses
  // non-empty connection ID.
  bool HasConnectionIdToConsume() const;
  absl::optional<QuicConnectionId> ConsumeOneConnectionId();

  // Returns true if the given connection ID is issued by the
  // QuicSelfIssuedConnectionIdManager and not retired locally yet. Called to
  // tell if a received packet has a valid connection ID.
  bool IsConnectionIdInUse(const QuicConnectionId& cid) const;

  virtual QuicConnectionId GenerateNewConnectionId(
      const QuicConnectionId& old_connection_id) const;

 private:
  friend class test::QuicConnectionIdManagerPeer;

  QuicNewConnectionIdFrame IssueNewConnectionId();

  // This should be set to the min of:
  // (1) # of active connection IDs that peer can maintain.
  // (2) maximum # of active connection IDs self plans to issue.
  size_t active_connection_id_limit_;
  const QuicClock* clock_;
  QuicConnectionIdManagerVisitorInterface* visitor_;
  // This tracks connection IDs issued to the peer but not retired by the peer.
  // Each pair is a connection ID and its sequence number.
  std::vector<std::pair<QuicConnectionId, uint64_t>> active_connection_ids_;
  // This tracks connection IDs retired by the peer but has not been retired
  // locally. Each pair is a connection ID and the time by which it should be
  // retired.
  std::vector<std::pair<QuicConnectionId, QuicTime>>
      to_be_retired_connection_ids_;
  // An alarm that fires when a connection ID should be retired.
  std::unique_ptr<QuicAlarm> retire_connection_id_alarm_;
  // State of the last issued connection Id.
  QuicConnectionId last_connection_id_;
  uint64_t next_connection_id_sequence_number_;
  // The sequence number of last connection ID consumed.
  uint64_t last_connection_id_consumed_by_self_sequence_number_;
};

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_QUIC_CONNECTION_ID_MANAGER_H_