summaryrefslogtreecommitdiffstats
path: root/net/quic/quic_connection.h
blob: 442e200f92f33328454d907e746d51dac474e039 (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
// 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.
//
// The entity that handles framing writes for a Quic client or server.
// Each QuicSession will have a connection associated with it.
//
// On the server side, the Dispatcher handles the raw reads, and hands off
// packets via ProcessUdpPacket for framing and processing.
//
// On the client side, the Connection handles the raw reads, as well as the
// processing.
//
// Note: this class is not thread-safe.

#ifndef NET_QUIC_QUIC_CONNECTION_H_
#define NET_QUIC_QUIC_CONNECTION_H_

#include <list>
#include <set>
#include <vector>

#include "base/hash_tables.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_protocol.h"

namespace net {

class QuicClock;
class QuicConnection;
class QuicEncrypter;
class QuicFecGroup;
class QuicRandom;
class QuicReceiptMetricsCollector;
class QuicSendScheduler;

class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
 public:
  typedef std::set<QuicPacketSequenceNumber> AckedPackets;

  virtual ~QuicConnectionVisitorInterface() {}

  // A simple visitor interface for dealing with data frames.  The session
  // should determine if all frames will be accepted, and return true if so.
  // If any frames can't be processed or buffered, none of the data should
  // be used, and the callee should return false.
  virtual bool OnPacket(const IPEndPoint& self_address,
                        const IPEndPoint& peer_address,
                        const QuicPacketHeader& header,
                        const std::vector<QuicStreamFrame>& frame) = 0;

  // Called when the stream is reset by the peer.
  virtual void OnRstStream(const QuicRstStreamFrame& frame) = 0;

  // Called when the connection is closed either locally by the framer, or
  // remotely by the peer.
  virtual void ConnectionClose(QuicErrorCode error, bool from_peer) = 0;

  // Called when packets are acked by the peer.
  virtual void OnAck(AckedPackets acked_packets) = 0;

  // Called when a blocked socket becomes writable.  If all pending bytes for
  // this visitor are consumed by the connection successfully this should
  // return true, otherwise it should return false.
  virtual bool OnCanWrite() = 0;
};

class NET_EXPORT_PRIVATE QuicConnectionHelperInterface {
 public:
  virtual ~QuicConnectionHelperInterface() {}

  // Sets the QuicConnection to be used by this helper.  This method
  // must only be called once.
  virtual void SetConnection(QuicConnection* connection) = 0;

  // Returns a QuicClock to be used for all time related functions.
  virtual const QuicClock* GetClock() const = 0;

  // Returns a QuicRandom to be used for all random number related functions.
  virtual QuicRandom* GetRandomGenerator() = 0;

  // Sends the packet out to the peer, possibly simulating packet
  // loss if FLAGS_fake_packet_loss_percentage is set.  If the write
  // succeeded, returns the number of bytes written.  If the write
  // failed, returns -1 and the error code will be copied to |*error|.
  virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
                                int* error) = 0;

  // Sets up an alarm to resend the packet with the given sequence number if we
  // haven't gotten an ack in the expected time frame.  Implementations must
  // invoke MaybeResendPacket when the alarm fires.  Implementations must also
  // handle the case where |this| is deleted before the alarm fires.
  virtual void SetResendAlarm(QuicPacketSequenceNumber sequence_number,
                              QuicTime::Delta delay) = 0;

  // Sets an alarm to send packets after |delay_in_us|.  Implementations must
  // invoke OnCanWrite when the alarm fires.  Implementations must also
  // handle the case where |this| is deleted before the alarm fires.
  virtual void SetSendAlarm(QuicTime::Delta delay) = 0;

  // Sets An alarm which fires when the connection may have timed out.
  // Implementations must call CheckForTimeout() and then reregister the alarm
  // if the connection has not yet timed out.
  virtual void SetTimeoutAlarm(QuicTime::Delta delay) = 0;

  // Returns true if a send alarm is currently set.
  virtual bool IsSendAlarmSet() = 0;

  // If a send alarm is currently set, this method unregisters it.  If
  // no send alarm is set, it does nothing.
  virtual void UnregisterSendAlarmIfRegistered() = 0;
};

class NET_EXPORT_PRIVATE QuicConnection : public QuicFramerVisitorInterface {
 public:
  // Constructs a new QuicConnection for the specified |guid| and |address|.
  // |helper| will be owned by this connection.
  QuicConnection(QuicGuid guid,
                 IPEndPoint address,
                 QuicConnectionHelperInterface* helper);
  virtual ~QuicConnection();

  // Send the data payload to the peer.
  // TODO(wtc): document the return value.
  size_t SendStreamData(QuicStreamId id,
                        base::StringPiece data,
                        QuicStreamOffset offset,
                        bool fin,
                        QuicPacketSequenceNumber* last_packet);
  // Send a stream reset frame to the peer.
  virtual void SendRstStream(QuicStreamId id,
                             QuicErrorCode error,
                             QuicStreamOffset offset);
  // Sends a connection close frame to the peer, and notifies the visitor of
  // the close.
  virtual void SendConnectionClose(QuicErrorCode error);

  // Processes an incoming UDP packet (consisting of a QuicEncryptedPacket) from
  // the peer.  If processing this packet permits a packet to be revived from
  // its FEC group that packet will be revived and processed.
  virtual void ProcessUdpPacket(const IPEndPoint& self_address,
                                const IPEndPoint& peer_address,
                                const QuicEncryptedPacket& packet);

  // Called when the underlying connection becomes writable to allow
  // queued writes to happen.  Returns false if the socket has become blocked.
  virtual bool OnCanWrite();

  // From QuicFramerVisitorInterface
  virtual void OnError(QuicFramer* framer) OVERRIDE;
  virtual void OnPacket(const IPEndPoint& self_address,
                        const IPEndPoint& peer_address) OVERRIDE;
  virtual void OnRevivedPacket() OVERRIDE;
  virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
  virtual void OnFecProtectedPayload(base::StringPiece payload) OVERRIDE;
  virtual void OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
  virtual void OnAckFrame(const QuicAckFrame& frame) OVERRIDE;
  virtual void OnCongestionFeedbackFrame(
      const QuicCongestionFeedbackFrame& frame) OVERRIDE;
  virtual void OnRstStreamFrame(const QuicRstStreamFrame& frame) OVERRIDE;
  virtual void OnConnectionCloseFrame(
      const QuicConnectionCloseFrame& frame) OVERRIDE;
  virtual void OnFecData(const QuicFecData& fec) OVERRIDE;
  virtual void OnPacketComplete() OVERRIDE;

  // Accessors
  void set_visitor(QuicConnectionVisitorInterface* visitor) {
    visitor_ = visitor;
  }
  const IPEndPoint& self_address() const { return self_address_; }
  const IPEndPoint& peer_address() const { return peer_address_; }
  QuicGuid guid() const { return guid_; }
  const QuicClock* clock() const { return clock_; }
  QuicRandom* random_generator() const { return random_generator_; }

  // Updates the internal state concerning which packets have been acked, and
  // sends an ack if new data frames have been received.
  void AckPacket(const QuicPacketHeader& header);

  // Called by a ResendAlarm when the timer goes off.  If the packet has been
  // acked it's a no op, otherwise the packet is resent and another alarm is
  // scheduled.
  void MaybeResendPacket(QuicPacketSequenceNumber sequence_number);

  QuicPacketCreator::Options* options() { return packet_creator_.options(); }

  bool connected() { return connected_; }

  size_t NumFecGroups() const { return group_map_.size(); }

  size_t NumQueuedPackets() const { return queued_packets_.size(); }

  // If the connection has timed out, this will close the connection and return
  // true.  Otherwise, it will return false and will reset the timeout alarm.
  bool CheckForTimeout();

  // Returns true of the next packet to be sent should be "lost" by
  // not actually writing it to the wire.
  bool ShouldSimulateLostPacket();

 protected:
  // Send a packet to the peer.  If should_resend is true, this packet contains
  // data, and contents will be resent with a new sequence number if we don't
  // get an ack.  If force is true, then the packet will be sent immediately and
  // the send scheduler will not be consulted.  If is_retransmit is true, this
  // packet is being retransmitted with a new sequence number.
  // TODO(wtc): none of the callers check the return value.
  virtual bool SendPacket(QuicPacketSequenceNumber number,
                          QuicPacket* packet,
                          bool should_resend,
                          bool force,
                          bool is_retransmit);

  // Make sure an ack we got from our peer is sane.
  bool ValidateAckFrame(const QuicAckFrame& incoming_ack);

  // These two are called by OnAckFrame to update the appropriate internal
  // state.
  //
  // Updates internal state based on incoming_ack.received_info
  void UpdatePacketInformationReceivedByPeer(
      const QuicAckFrame& incoming_ack);
  // Updates internal state based in incoming_ack.sent_info
  void UpdatePacketInformationSentByPeer(const QuicAckFrame& incoming_ack);

  // Utility which sets SetLeastUnacked to least_unacked, and updates the list
  // of non-retransmitting packets accordingly.
  void SetLeastUnacked(QuicPacketSequenceNumber least_unacked);

  // Helper to update least unacked.  If acked_sequence_number was not the least
  // unacked packet, this is a no-op.  If it was the least least unacked packet,
  // This finds the new least unacked packet and updates the outgoing ack frame.
  void UpdateLeastUnacked(QuicPacketSequenceNumber acked_sequence_number);

  QuicConnectionHelperInterface* helper() { return helper_; }

 private:
  friend class QuicConnectionPeer;
  // Packets which have not been written to the wire.
  struct QueuedPacket {
    QueuedPacket(QuicPacketSequenceNumber sequence_number,
                 QuicPacket* packet,
                 bool resend,
                 bool retransmit)
        : sequence_number(sequence_number),
          packet(packet),
          resend(resend),
          retransmit(retransmit) {
    }

    QuicPacketSequenceNumber sequence_number;
    QuicPacket* packet;
    bool resend;
    bool retransmit;
  };

  struct UnackedPacket {
    explicit UnackedPacket(QuicPacket* packet)
        : packet(packet), number_nacks(0) {
    }
    QuicPacket* packet;
    uint8 number_nacks;
  };

  typedef std::list<QueuedPacket> QueuedPacketList;
  typedef base::hash_map<QuicPacketSequenceNumber,
      UnackedPacket> UnackedPacketMap;
  typedef std::map<QuicFecGroupNumber, QuicFecGroup*> FecGroupMap;

  // The amount of time we wait before resending a packet.
  static const QuicTime::Delta DefaultResendTime() {
    return QuicTime::Delta::FromMilliseconds(500);
  }

  // Sets up a packet with an QuicAckFrame and sends it out.
  void SendAck();

  // If a packet can be revived from the current FEC group, then
  // revive and process the packet.
  void MaybeProcessRevivedPacket();

  // Get the FEC group associate with the last processed packet.
  QuicFecGroup* GetFecGroup();

  // Fills the ack frame with the appropriate latched information.
  void FillAckFrame(QuicAckFrame* ack);

  // Closes any FEC groups protecting packets before |sequence_number|.
  void CloseFecGroupsBefore(QuicPacketSequenceNumber sequence_number);

  QuicConnectionHelperInterface* helper_;
  QuicFramer framer_;
  const QuicClock* clock_;
  QuicRandom* random_generator_;

  const QuicGuid guid_;
  IPEndPoint self_address_;
  IPEndPoint peer_address_;

  bool last_packet_revived_;  // True if the last packet was revived from FEC.
  size_t last_size_;  // Size of the last received packet.
  QuicPacketHeader last_header_;
  std::vector<QuicStreamFrame> frames_;

  QuicAckFrame outgoing_ack_;
  QuicCongestionFeedbackFrame outgoing_congestion_feedback_;

  // Track some client state so we can do less bookkeeping
  //
  QuicPacketSequenceNumber largest_seen_packet_with_ack_;
  QuicPacketSequenceNumber least_packet_awaiting_ack_;

  // When new packets are created which may be resent, they are added
  // to this map, which contains owning pointers.
  UnackedPacketMap unacked_packets_;

  // When packets could not be sent because the socket was not writable,
  // they are added to this list.  For packets that are not resendable, this
  // list contains owning pointers, since they are not added to
  // unacked_packets_.
  QueuedPacketList queued_packets_;

  // True when the socket becomes unwritable.
  bool write_blocked_;

  FecGroupMap group_map_;
  QuicPacketHeader revived_header_;
  scoped_array<char> revived_payload_;

  QuicConnectionVisitorInterface* visitor_;
  QuicPacketCreator packet_creator_;

  // Network idle time before we kill of this connection.
  const QuicTime::Delta timeout_;
  // The time that we got or tried to send a packet for this connection.
  QuicTime time_of_last_packet_;

  scoped_ptr<QuicReceiptMetricsCollector> collector_;

  // Scheduler which drives packet send rate.
  scoped_ptr<QuicSendScheduler> scheduler_;

  // The number of packets we resent since sending the last ack.
  uint8 packets_resent_since_last_ack_;

  // True by default.  False if we've received or sent an explicit connection
  // close.
  bool connected_;

  DISALLOW_COPY_AND_ASSIGN(QuicConnection);
};

}  // namespace net

#endif  // NET_QUIC_QUIC_CONNECTION_H_