summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h
blob: a4c26780d40396e66979cab70aa8c36ca9e25071 (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
// Copyright (c) 2017 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.

#ifndef QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_
#define QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_

#include <string>

#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"

namespace quic {

class QuicSession;

namespace test {
class QuicControlFrameManagerPeer;
}  // namespace test

// Control frame manager contains a list of sent control frames with valid
// control frame IDs. Control frames without valid control frame IDs include:
// (1) non-retransmittable frames (e.g., ACK_FRAME, PADDING_FRAME,
// STOP_WAITING_FRAME, etc.), (2) CONNECTION_CLOSE and IETF Quic
// APPLICATION_CLOSE frames.
// New control frames are added to the tail of the list when they are added to
// the generator. Control frames are removed from the head of the list when they
// get acked. Control frame manager also keeps track of lost control frames
// which need to be retransmitted.
class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
 public:
  explicit QuicControlFrameManager(QuicSession* session);
  QuicControlFrameManager(const QuicControlFrameManager& other) = delete;
  QuicControlFrameManager(QuicControlFrameManager&& other) = delete;
  ~QuicControlFrameManager();

  // Tries to send a WINDOW_UPDATE_FRAME. Buffers the frame if it cannot be sent
  // immediately.
  void WriteOrBufferRstStream(QuicControlFrameId id,
                              QuicRstStreamErrorCode error,
                              QuicStreamOffset bytes_written);

  // Tries to send a GOAWAY_FRAME. Buffers the frame if it cannot be sent
  // immediately.
  void WriteOrBufferGoAway(QuicErrorCode error,
                           QuicStreamId last_good_stream_id,
                           const std::string& reason);

  // Tries to send a WINDOW_UPDATE_FRAME. Buffers the frame if it cannot be sent
  // immediately.
  void WriteOrBufferWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset);

  // Tries to send a BLOCKED_FRAME. Buffers the frame if it cannot be sent
  // immediately.
  void WriteOrBufferBlocked(QuicStreamId id);

  // Tries to send a STREAMS_BLOCKED Frame. Buffers the frame if it cannot be
  // sent immediately.
  void WriteOrBufferStreamsBlocked(QuicStreamCount count, bool unidirectional);

  // Tries to send a MAX_STREAMS Frame. Buffers the frame if it cannot be sent
  // immediately.
  void WriteOrBufferMaxStreams(QuicStreamCount count, bool unidirectional);

  // Tries to send an IETF-QUIC STOP_SENDING frame. The frame is buffered if it
  // can not be sent immediately.
  void WriteOrBufferStopSending(uint16_t code, QuicStreamId stream_id);

  // Sends a PING_FRAME. Do not send PING if there is buffered frames.
  void WritePing();

  // Called when |frame| gets acked. Returns true if |frame| gets acked for the
  // first time, return false otherwise.
  bool OnControlFrameAcked(const QuicFrame& frame);

  // Called when |frame| is considered as lost.
  void OnControlFrameLost(const QuicFrame& frame);

  // Called by the session when the connection becomes writable.
  void OnCanWrite();

  // Retransmit |frame| if it is still outstanding. Returns false if the frame
  // does not get retransmitted because the connection is blocked. Otherwise,
  // returns true.
  bool RetransmitControlFrame(const QuicFrame& frame);

  // Returns true if |frame| is outstanding and waiting to be acked. Returns
  // false otherwise.
  bool IsControlFrameOutstanding(const QuicFrame& frame) const;

  // Returns true if there is any lost control frames waiting to be
  // retransmitted.
  bool HasPendingRetransmission() const;

  // Returns true if there are any lost or new control frames waiting to be
  // sent.
  bool WillingToWrite() const;

 private:
  friend class test::QuicControlFrameManagerPeer;

  // Tries to write buffered control frames to the peer.
  void WriteBufferedFrames();

  // Called when |frame| is sent for the first time or gets retransmitted.
  void OnControlFrameSent(const QuicFrame& frame);

  // Writes pending retransmissions if any.
  void WritePendingRetransmission();

  // Called when frame with |id| gets acked. Returns true if |id| gets acked for
  // the first time, return false otherwise.
  bool OnControlFrameIdAcked(QuicControlFrameId id);

  // Retrieves the next pending retransmission. This must only be called when
  // there are pending retransmissions.
  QuicFrame NextPendingRetransmission() const;

  // Returns true if there are buffered frames waiting to be sent for the first
  // time.
  bool HasBufferedFrames() const;

  // Writes or buffers a control frame.  Frame is buffered if there already
  // are frames waiting to be sent. If no others waiting, will try to send the
  // frame.
  void WriteOrBufferQuicFrame(QuicFrame frame);

  QuicDeque<QuicFrame> control_frames_;

  // Id of latest saved control frame. 0 if no control frame has been saved.
  QuicControlFrameId last_control_frame_id_;

  // The control frame at the 0th index of control_frames_.
  QuicControlFrameId least_unacked_;

  // ID of the least unsent control frame.
  QuicControlFrameId least_unsent_;

  // TODO(fayang): switch to linked_hash_set when chromium supports it. The bool
  // is not used here.
  // Lost control frames waiting to be retransmitted.
  QuicLinkedHashMap<QuicControlFrameId, bool> pending_retransmissions_;

  // Pointer to the owning QuicSession object.
  QuicSession* session_;

  // Last sent window update frame for each stream.
  QuicSmallMap<QuicStreamId, QuicControlFrameId, 10> window_update_frames_;
};

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_