OLD | NEW |
| (Empty) |
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/quic/quic_buffered_packet_store.h" | |
6 | |
7 #include <list> | |
8 | |
9 #include "base/stl_util.h" | |
10 | |
11 using std::list; | |
12 | |
13 namespace net { | |
14 | |
15 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; | |
16 typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult; | |
17 typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList; | |
18 | |
19 // Max number of connections this store can keep track. | |
20 static const size_t kDefaultMaxConnectionsInStore = 100; | |
21 | |
22 namespace { | |
23 | |
24 // This alarm removes expired entries in map each time this alarm fires. | |
25 class ConnectionExpireAlarm : public QuicAlarm::Delegate { | |
26 public: | |
27 explicit ConnectionExpireAlarm(QuicBufferedPacketStore* store) | |
28 : connection_store_(store) {} | |
29 | |
30 void OnAlarm() override { connection_store_->OnExpirationTimeout(); } | |
31 | |
32 // Disallow copy and asign. | |
33 ConnectionExpireAlarm(const ConnectionExpireAlarm&) = delete; | |
34 ConnectionExpireAlarm& operator=(const ConnectionExpireAlarm&) = delete; | |
35 | |
36 private: | |
37 QuicBufferedPacketStore* connection_store_; | |
38 }; | |
39 | |
40 } // namespace | |
41 | |
42 BufferedPacket::BufferedPacket(std::unique_ptr<QuicReceivedPacket> packet, | |
43 IPEndPoint server_address, | |
44 IPEndPoint client_address) | |
45 : packet(std::move(packet)), | |
46 server_address(server_address), | |
47 client_address(client_address) {} | |
48 | |
49 BufferedPacket::BufferedPacket(BufferedPacket&& other) = default; | |
50 | |
51 BufferedPacket& BufferedPacket::operator=(BufferedPacket&& other) = default; | |
52 | |
53 BufferedPacket::~BufferedPacket() {} | |
54 | |
55 BufferedPacketList::BufferedPacketList() : creation_time(QuicTime::Zero()) {} | |
56 | |
57 BufferedPacketList::BufferedPacketList(BufferedPacketList&& other) = default; | |
58 | |
59 BufferedPacketList& BufferedPacketList::operator=(BufferedPacketList&& other) = | |
60 default; | |
61 | |
62 BufferedPacketList::~BufferedPacketList() {} | |
63 | |
64 QuicBufferedPacketStore::QuicBufferedPacketStore( | |
65 VisitorInterface* visitor, | |
66 const QuicClock* clock, | |
67 QuicAlarmFactory* alarm_factory) | |
68 : connection_life_span_( | |
69 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs)), | |
70 visitor_(visitor), | |
71 clock_(clock), | |
72 expiration_alarm_( | |
73 alarm_factory->CreateAlarm(new ConnectionExpireAlarm(this))) {} | |
74 | |
75 QuicBufferedPacketStore::~QuicBufferedPacketStore() {} | |
76 | |
77 EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket( | |
78 QuicConnectionId connection_id, | |
79 const QuicReceivedPacket& packet, | |
80 IPEndPoint server_address, | |
81 IPEndPoint client_address) { | |
82 if (!ContainsKey(undecryptable_packets_, connection_id) && | |
83 undecryptable_packets_.size() >= kDefaultMaxConnectionsInStore) { | |
84 // Drop the packet if store can't keep track of more connections. | |
85 return TOO_MANY_CONNECTIONS; | |
86 } else if (!ContainsKey(undecryptable_packets_, connection_id)) { | |
87 undecryptable_packets_.emplace( | |
88 std::make_pair(connection_id, BufferedPacketList())); | |
89 } | |
90 CHECK(ContainsKey(undecryptable_packets_, connection_id)); | |
91 BufferedPacketList& queue = | |
92 undecryptable_packets_.find(connection_id)->second; | |
93 | |
94 if (queue.buffered_packets.size() >= kDefaultMaxUndecryptablePackets) { | |
95 // If there are kMaxBufferedPacketsPerConnection packets buffered up for | |
96 // this connection, drop the current packet. | |
97 return TOO_MANY_PACKETS; | |
98 } | |
99 | |
100 if (queue.buffered_packets.empty()) { | |
101 // If this is the first packet arrived on a new connection, initialize the | |
102 // creation time. | |
103 queue.creation_time = clock_->ApproximateNow(); | |
104 } | |
105 | |
106 BufferedPacket new_entry(std::unique_ptr<QuicReceivedPacket>(packet.Clone()), | |
107 server_address, client_address); | |
108 | |
109 queue.buffered_packets.push_back(std::move(new_entry)); | |
110 | |
111 if (!expiration_alarm_->IsSet()) { | |
112 expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_); | |
113 } | |
114 return SUCCESS; | |
115 } | |
116 | |
117 bool QuicBufferedPacketStore::HasBufferedPackets( | |
118 QuicConnectionId connection_id) const { | |
119 return ContainsKey(undecryptable_packets_, connection_id); | |
120 } | |
121 | |
122 list<BufferedPacket> QuicBufferedPacketStore::DeliverPackets( | |
123 QuicConnectionId connection_id) { | |
124 list<BufferedPacket> packets_to_deliver; | |
125 auto it = undecryptable_packets_.find(connection_id); | |
126 if (it != undecryptable_packets_.end()) { | |
127 packets_to_deliver = std::move(it->second.buffered_packets); | |
128 undecryptable_packets_.erase(connection_id); | |
129 } | |
130 return packets_to_deliver; | |
131 } | |
132 | |
133 void QuicBufferedPacketStore::OnExpirationTimeout() { | |
134 QuicTime expiration_time = clock_->ApproximateNow() - connection_life_span_; | |
135 while (!undecryptable_packets_.empty()) { | |
136 auto& entry = undecryptable_packets_.front(); | |
137 if (entry.second.creation_time > expiration_time) { | |
138 break; | |
139 } | |
140 visitor_->OnExpiredPackets(entry.first, std::move(entry.second)); | |
141 undecryptable_packets_.erase(undecryptable_packets_.begin()); | |
142 } | |
143 if (!undecryptable_packets_.empty()) { | |
144 expiration_alarm_->Set(clock_->ApproximateNow() + connection_life_span_); | |
145 } | |
146 } | |
147 | |
148 } // namespace net | |
OLD | NEW |