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