| 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 |