OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/quic_dispatcher.h" | 5 #include "net/quic/quic_dispatcher.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 | 8 |
9 #include "base/debug/stack_trace.h" | 9 #include "base/debug/stack_trace.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 // ProcessPacket will cause the packet to be dispatched in | 195 // ProcessPacket will cause the packet to be dispatched in |
196 // OnUnauthenticatedPublicHeader, or sent to the time wait list manager | 196 // OnUnauthenticatedPublicHeader, or sent to the time wait list manager |
197 // in OnAuthenticatedHeader. | 197 // in OnAuthenticatedHeader. |
198 framer_.ProcessPacket(packet); | 198 framer_.ProcessPacket(packet); |
199 // TODO(rjshade): Return a status describing if/why a packet was dropped, | 199 // TODO(rjshade): Return a status describing if/why a packet was dropped, |
200 // and log somehow. Maybe expose as a varz. | 200 // and log somehow. Maybe expose as a varz. |
201 } | 201 } |
202 | 202 |
203 bool QuicDispatcher::OnUnauthenticatedPublicHeader( | 203 bool QuicDispatcher::OnUnauthenticatedPublicHeader( |
204 const QuicPacketPublicHeader& header) { | 204 const QuicPacketPublicHeader& header) { |
205 QuicSession* session = nullptr; | |
206 | |
207 // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC. | 205 // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC. |
208 // Given that we can't even send a reply rejecting the packet, just black hole | 206 // Given that we can't even send a reply rejecting the packet, just black hole |
209 // it. | 207 // it. |
210 if (current_client_address_.port() == 0) { | 208 if (current_client_address_.port() == 0) { |
211 return false; | 209 return false; |
212 } | 210 } |
213 | 211 |
| 212 // The session that we have identified as the one to which this packet |
| 213 // belongs. |
| 214 QuicSession* session = nullptr; |
214 QuicConnectionId connection_id = header.connection_id; | 215 QuicConnectionId connection_id = header.connection_id; |
215 SessionMap::iterator it = session_map_.find(connection_id); | 216 SessionMap::iterator it = session_map_.find(connection_id); |
216 if (it == session_map_.end()) { | 217 if (it == session_map_.end()) { |
217 if (header.reset_flag) { | |
218 return false; | |
219 } | |
220 if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) { | 218 if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) { |
221 return HandlePacketForTimeWait(header); | 219 return HandlePacketForTimeWait(header); |
222 } | 220 } |
223 | 221 |
224 // Ensure the packet has a version negotiation bit set before creating a new | 222 // The packet has an unknown connection ID. |
225 // session for it. All initial packets for a new connection are required to | 223 // If the packet is a public reset, there is nothing we must do or can do. |
226 // have the flag set. Otherwise it may be a stray packet. | 224 if (header.reset_flag) { |
227 if (header.version_flag) { | 225 return false; |
228 session = CreateQuicSession(connection_id, current_server_address_, | |
229 current_client_address_); | |
230 } | 226 } |
231 | 227 |
232 if (session == nullptr) { | 228 // All packets within a connection sent by a client before receiving a |
233 DVLOG(1) << "Failed to create session for " << connection_id; | 229 // response from the server are required to have the version negotiation |
| 230 // flag set. Since this may be a client continuing a connection we lost |
| 231 // track of via server restart, send a rejection to fast-fail the |
| 232 // connection. |
| 233 if (!header.version_flag) { |
| 234 DVLOG(1) << "Packet without version arrived for unknown connection ID " |
| 235 << connection_id; |
234 // Add this connection_id fo the time-wait state, to safely reject future | 236 // Add this connection_id fo the time-wait state, to safely reject future |
235 // packets. | 237 // packets. |
236 | 238 QuicVersion version = supported_versions_.front(); |
237 if (header.version_flag && | |
238 !framer_.IsSupportedVersion(header.versions.front())) { | |
239 // TODO(ianswett): Produce a no-version version negotiation packet. | |
240 return false; | |
241 } | |
242 | |
243 // Use the version in the packet if possible, otherwise assume the latest. | |
244 QuicVersion version = header.version_flag ? header.versions.front() : | |
245 supported_versions_.front(); | |
246 time_wait_list_manager_->AddConnectionIdToTimeWait(connection_id, version, | 239 time_wait_list_manager_->AddConnectionIdToTimeWait(connection_id, version, |
247 nullptr); | 240 nullptr); |
248 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); | 241 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); |
249 return HandlePacketForTimeWait(header); | 242 return HandlePacketForTimeWait(header); |
250 } | 243 } |
251 DVLOG(1) << "Created new session for " << connection_id; | 244 |
252 session_map_.insert(std::make_pair(connection_id, session)); | 245 session = AdditionalValidityChecksThenCreateSession(header, connection_id); |
| 246 if (session == nullptr) { |
| 247 return false; |
| 248 } |
253 } else { | 249 } else { |
254 session = it->second; | 250 session = it->second; |
255 } | 251 } |
256 | 252 |
257 session->connection()->ProcessUdpPacket( | 253 session->connection()->ProcessUdpPacket( |
258 current_server_address_, current_client_address_, *current_packet_); | 254 current_server_address_, current_client_address_, *current_packet_); |
259 | 255 |
260 // Do not parse the packet further. The session will process it completely. | 256 // Do not parse the packet further. The session methods called above have |
| 257 // processed it completely. |
261 return false; | 258 return false; |
262 } | 259 } |
263 | 260 |
| 261 QuicSession* QuicDispatcher::AdditionalValidityChecksThenCreateSession( |
| 262 const QuicPacketPublicHeader& header, |
| 263 QuicConnectionId connection_id) { |
| 264 QuicSession* session = CreateQuicSession( |
| 265 connection_id, current_server_address_, current_client_address_); |
| 266 |
| 267 if (session == nullptr) { |
| 268 DVLOG(1) << "Failed to create session for " << connection_id; |
| 269 |
| 270 if (!framer_.IsSupportedVersion(header.versions.front())) { |
| 271 // TODO(ianswett): Produce packet saying "no supported version". |
| 272 return nullptr; |
| 273 } |
| 274 |
| 275 // Add this connection_id to the time-wait state, to safely reject future |
| 276 // packets. |
| 277 QuicVersion version = header.versions.front(); |
| 278 time_wait_list_manager_->AddConnectionIdToTimeWait(connection_id, version, |
| 279 nullptr); |
| 280 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)); |
| 281 HandlePacketForTimeWait(header); |
| 282 |
| 283 return nullptr; |
| 284 } |
| 285 |
| 286 DVLOG(1) << "Created new session for " << connection_id; |
| 287 session_map_.insert(std::make_pair(connection_id, session)); |
| 288 |
| 289 return session; |
| 290 } |
| 291 |
264 void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { | 292 void QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { |
265 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( | 293 DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait( |
266 header.public_header.connection_id)); | 294 header.public_header.connection_id)); |
267 time_wait_list_manager_->ProcessPacket(current_server_address_, | 295 time_wait_list_manager_->ProcessPacket(current_server_address_, |
268 current_client_address_, | 296 current_client_address_, |
269 header.public_header.connection_id, | 297 header.public_header.connection_id, |
270 header.packet_sequence_number, | 298 header.packet_sequence_number, |
271 *current_packet_); | 299 *current_packet_); |
272 } | 300 } |
273 | 301 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 // be parsed correctly. | 416 // be parsed correctly. |
389 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( | 417 framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId( |
390 header.connection_id)); | 418 header.connection_id)); |
391 | 419 |
392 // Continue parsing the packet to extract the sequence number. Then | 420 // Continue parsing the packet to extract the sequence number. Then |
393 // send it to the time wait manager in OnUnathenticatedHeader. | 421 // send it to the time wait manager in OnUnathenticatedHeader. |
394 return true; | 422 return true; |
395 } | 423 } |
396 | 424 |
397 } // namespace net | 425 } // namespace net |
OLD | NEW |