summaryrefslogtreecommitdiff
path: root/chromium/net/quic/quic_packet_generator.h
blob: 1ff04882ae11380f0e1d4aa46e0e2d712a79e4ad (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
// 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.
//
// Responsible for generating packets on behalf of a QuicConnection.
// Packets are serialized just-in-time.  Control frames are queued.
// Ack and Feedback frames will be requested from the Connection
// just-in-time.  When a packet needs to be sent, the Generator
// will serialize a packet and pass it to QuicConnection::SendOrQueuePacket()
//
// The Generator's mode of operation is controlled by two conditions:
//
// 1) Is the Delegate writable?
//
// If the Delegate is not writable, then no operations will cause
// a packet to be serialized.  In particular:
// * SetShouldSendAck will simply record that an ack is to be sent.
// * AddControlFrame will enqueue the control frame.
// * ConsumeData will do nothing.
//
// If the Delegate is writable, then the behavior depends on the second
// condition:
//
// 2) Is the Generator in batch mode?
//
// If the Generator is NOT in batch mode, then each call to a write
// operation will serialize one or more packets.  The contents will
// include any previous queued frames.  If an ack should be sent
// but has not been sent, then the Delegate will be asked to create
// an Ack frame which will then be included in the packet.  When
// the write call completes, the current packet will be serialized
// and sent to the Delegate, even if it is not full.
//
// If the Generator is in batch mode, then each write operation will
// add data to the "current" packet.  When the current packet becomes
// full, it will be serialized and sent to the packet.  When batch
// mode is ended via |FinishBatchOperations|, the current packet
// will be serialzied, even if it is not full.
//
// FEC behavior also depends on batch mode.  In batch mode, FEC packets
// will be sent after |max_packets_per_group| have been sent, as well
// as after batch operations are complete.  When not in batch mode,
// an FEC packet will be sent after each write call completes.
//
// TODO(rch): This behavior should probably be tuned.  When not in batch
// mode, we should probably set a timer so that several independent
// operations can be grouped into the same FEC group.
//
// When an FEC packet is generated, it will be send to the Delegate,
// even if the Delegate has become unwritable after handling the
// data packet immediately proceeding the FEC packet.

#ifndef NET_QUIC_QUIC_PACKET_GENERATOR_H_
#define NET_QUIC_QUIC_PACKET_GENERATOR_H_

#include "net/quic/quic_packet_creator.h"

namespace net {

class QuicAckNotifier;

class NET_EXPORT_PRIVATE QuicPacketGenerator {
 public:
  class NET_EXPORT_PRIVATE DelegateInterface {
   public:
    virtual ~DelegateInterface() {}
    virtual bool ShouldGeneratePacket(TransmissionType transmission_type,
                                      HasRetransmittableData retransmittable,
                                      IsHandshake handshake) = 0;
    virtual QuicAckFrame* CreateAckFrame() = 0;
    virtual QuicCongestionFeedbackFrame* CreateFeedbackFrame() = 0;
    // Takes ownership of |packet.packet| and |packet.retransmittable_frames|.
    virtual bool OnSerializedPacket(const SerializedPacket& packet) = 0;
    virtual void CloseConnection(QuicErrorCode error, bool from_peer) = 0;
  };

  // Interface which gets callbacks from the QuicPacketGenerator at interesting
  // points.  Implementations must not mutate the state of the generator
  // as a result of these callbacks.
  class NET_EXPORT_PRIVATE DebugDelegateInterface {
   public:
    virtual ~DebugDelegateInterface() {}

    // Called when a frame has been added to the current packet.
    virtual void OnFrameAddedToPacket(const QuicFrame& frame) = 0;
  };

  QuicPacketGenerator(DelegateInterface* delegate,
                      DebugDelegateInterface* debug_delegate,
                      QuicPacketCreator* creator);

  virtual ~QuicPacketGenerator();

  // Indicates that an ACK frame should be sent.  If |also_send_feedback| is
  // true, then it also indicates a CONGESTION_FEEDBACK frame should be sent.
  // The contents of the frame(s) will be generated via a call to the delegates
  // CreateAckFrame() and CreateFeedbackFrame() when the packet is serialized.
  void SetShouldSendAck(bool also_send_feedback);
  void AddControlFrame(const QuicFrame& frame);

  // Given some data, may consume part or all of it and pass it to the
  // packet creator to be serialized into packets. If not in batch
  // mode, these packets will also be sent during this call. Also
  // attaches a QuicAckNotifier to any created stream frames, which
  // will be called once the frame is ACKed by the peer. The
  // QuicAckNotifier is owned by the QuicConnection. |notifier| may
  // be NULL.
  QuicConsumedData ConsumeData(QuicStreamId id,
                               const IOVector& data,
                               QuicStreamOffset offset,
                               bool fin,
                               QuicAckNotifier* notifier);

  // Indicates whether batch mode is currently enabled.
  bool InBatchMode();
  // Disables flushing.
  void StartBatchOperations();
  // Enables flushing and flushes queued data which can be sent.
  void FinishBatchOperations();

  // Flushes all queued frames, even frames which are not sendable.
  void FlushAllQueuedFrames();

  bool HasQueuedFrames() const;

  void set_debug_delegate(DebugDelegateInterface* debug_delegate) {
    debug_delegate_ = debug_delegate;
  }

 private:
  void SendQueuedFrames(bool flush);

  // Test to see if we have pending ack, feedback, or control frames.
  bool HasPendingFrames() const;
  // Test to see if the addition of a pending frame (which might be
  // retransmittable) would still allow the resulting packet to be sent now.
  bool CanSendWithNextPendingFrameAddition() const;
  // Add exactly one pending frame, preferring ack over feedback over control
  // frames.
  bool AddNextPendingFrame();

  bool AddFrame(const QuicFrame& frame);

  void SerializeAndSendPacket();

  DelegateInterface* delegate_;
  DebugDelegateInterface* debug_delegate_;

  QuicPacketCreator* packet_creator_;
  QuicFrames queued_control_frames_;

  // True if batch mode is currently enabled.
  bool batch_mode_;

  // Flags to indicate the need for just-in-time construction of a frame.
  bool should_send_ack_;
  bool should_send_feedback_;
  // If we put a non-retransmittable frame (namley ack or feedback frame) in
  // this packet, then we have to hold a reference to it until we flush (and
  // serialize it). Retransmittable frames are referenced elsewhere so that they
  // can later be (optionally) retransmitted.
  scoped_ptr<QuicAckFrame> pending_ack_frame_;
  scoped_ptr<QuicCongestionFeedbackFrame> pending_feedback_frame_;

  DISALLOW_COPY_AND_ASSIGN(QuicPacketGenerator);
};

}  // namespace net

#endif  // NET_QUIC_QUIC_PACKET_GENERATOR_H_