Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/quic/quic_framer.h" | |
| 6 | |
| 7 #include "base/hash_tables.h" | |
| 8 #include "net/quic/crypto/quic_decrypter.h" | |
| 9 #include "net/quic/crypto/quic_encrypter.h" | |
| 10 #include "net/quic/quic_data_reader.h" | |
| 11 #include "net/quic/quic_data_writer.h" | |
| 12 #include "net/quic/quic_utils.h" | |
| 13 | |
| 14 using base::hash_set; | |
| 15 using base::StringPiece; | |
| 16 | |
| 17 namespace net { | |
| 18 | |
| 19 QuicFramer::QuicFramer(QuicDecrypter* decrypter, QuicEncrypter* encrypter) | |
| 20 : visitor_(NULL), | |
| 21 fec_builder_(NULL), | |
| 22 error_(QUIC_NO_ERROR), | |
| 23 decrypter_(decrypter), | |
| 24 encrypter_(encrypter) { | |
| 25 } | |
| 26 | |
| 27 QuicFramer::~QuicFramer() {} | |
| 28 | |
| 29 bool QuicFramer::ConstructFragementDataPacket( | |
| 30 const QuicPacketHeader& header, | |
| 31 const QuicFragments& fragments, | |
| 32 QuicPacket** packet) { | |
| 33 // compute the length of the packet | |
|
jar (doing other things)
2012/10/14 23:04:38
nit: comments start with Upper-case, and end with
Ryan Hamilton
2012/10/15 21:22:08
Done.
| |
| 34 size_t len = kPacketHeaderSize; | |
| 35 len += 1; // fragment count | |
|
jar (doing other things)
2012/10/14 23:04:38
nit: IMO, nicer would be sizeof(some_named_member_
Ryan Hamilton
2012/10/15 21:22:08
That's a bit tricky because the sizeof(member_) is
| |
| 36 for (size_t i = 0; i < fragments.size(); ++i) { | |
| 37 len += 1; // space for the 8 bit type | |
| 38 len += ComputeFragmentPayloadLength(fragments[i]); | |
| 39 } | |
| 40 | |
| 41 QuicDataWriter writer(len); | |
| 42 | |
| 43 if (!WritePacketHeader(header, &writer)) { | |
| 44 return false; | |
| 45 } | |
| 46 | |
| 47 // fragment count | |
| 48 if (!writer.WriteUInt8(fragments.size())) { | |
|
jar (doing other things)
2012/10/14 23:04:38
Do we have guarantees that framents.size() is less
Ryan Hamilton
2012/10/15 21:22:08
Added DCHECK
| |
| 49 return false; | |
| 50 } | |
| 51 | |
| 52 for (size_t i = 0; i < fragments.size(); ++i) { | |
| 53 const QuicFragment& fragment = fragments[i]; | |
| 54 if (!writer.WriteUInt8(fragment.type)) { | |
| 55 return false; | |
| 56 } | |
| 57 | |
| 58 switch (fragment.type) { | |
| 59 case STREAM_FRAGMENT: | |
| 60 if (!AppendStreamFragmentPayload(*fragment.stream_fragment, | |
| 61 &writer)) { | |
| 62 return false; | |
| 63 } | |
| 64 break; | |
| 65 case PDU_FRAGMENT: | |
| 66 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 67 case ACK_FRAGMENT: | |
| 68 if (!AppendAckFragmentPayload(*fragment.ack_fragment, &writer)) { | |
| 69 return false; | |
| 70 } | |
| 71 break; | |
| 72 case RST_STREAM_FRAGMENT: | |
| 73 if (!AppendRstStreamFragmentPayload(*fragment.rst_stream_fragment, | |
| 74 &writer)) { | |
| 75 return false; | |
| 76 } | |
| 77 break; | |
| 78 case CONNECTION_CLOSE_FRAGMENT: | |
| 79 if (!AppendConnectionCloseFragmentPayload( | |
| 80 *fragment.connection_close_fragment, &writer)) { | |
| 81 return false; | |
| 82 } | |
| 83 break; | |
| 84 default: | |
| 85 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 *packet = new QuicPacket(writer.take(), len, true); | |
| 90 if (fec_builder_) { | |
| 91 fec_builder_->OnBuiltFecProtectedPayload(header, | |
| 92 (*packet)->FecProtectedData()); | |
| 93 } | |
| 94 | |
| 95 return true; | |
| 96 } | |
| 97 | |
| 98 bool QuicFramer::ConstructFecPacket(const QuicPacketHeader& header, | |
| 99 const QuicFecData& fec, | |
| 100 QuicPacket** packet) { | |
| 101 // compute the length of the packet | |
| 102 size_t len = kPacketHeaderSize; | |
| 103 len += 6; // first protected packet sequence number | |
| 104 len += fec.redundancy.length(); | |
| 105 | |
| 106 QuicDataWriter writer(len); | |
| 107 | |
| 108 if (!WritePacketHeader(header, &writer)) { | |
| 109 return false; | |
| 110 } | |
| 111 | |
| 112 if (!writer.WriteUInt48(fec.first_protected_packet_sequence_number)) { | |
| 113 return false; | |
| 114 } | |
| 115 | |
| 116 if (!writer.WriteBytes(fec.redundancy.data(), fec.redundancy.length())) { | |
| 117 return false; | |
| 118 } | |
| 119 | |
| 120 *packet = new QuicPacket(writer.take(), len, true); | |
| 121 | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 void QuicFramer::IncrementRetransmitCount(QuicPacket* packet) { | |
| 126 DCHECK_GT(packet->length(), kPacketHeaderSize); | |
|
jar (doing other things)
2012/10/14 23:04:38
A CHECK is a bit tempting here. I'm not sure abou
Ryan Hamilton
2012/10/15 21:22:08
In general we really don't want the server to cras
jar (doing other things)
2012/10/15 23:54:32
It sure seems evil to increment memory that is not
Ryan Hamilton
2012/10/16 00:03:56
Done. I'll attempt to land a CHECK on the server
| |
| 127 | |
| 128 ++packet->mutable_data()[kRetransmissionOffset]; | |
| 129 } | |
| 130 | |
| 131 uint8 QuicFramer::GetRetransmitCount(QuicPacket* packet) { | |
| 132 DCHECK_GT(packet->length(), kPacketHeaderSize); | |
| 133 | |
| 134 return packet->mutable_data()[kRetransmissionOffset]; | |
| 135 } | |
| 136 | |
| 137 bool QuicFramer::ProcessPacket(const IPEndPoint& peer_address, | |
| 138 const QuicEncryptedPacket& packet) { | |
| 139 LOG(INFO) << "here!"; | |
|
jar (doing other things)
2012/10/14 23:04:38
nit: DLOG
Ryan Hamilton
2012/10/15 21:22:08
Removed.
| |
| 140 DCHECK(!reader_.get()); | |
| 141 reader_.reset(new QuicDataReader(packet.data(), packet.length())); | |
| 142 visitor_->OnPacket(peer_address); | |
| 143 | |
| 144 // First parse the packet header. | |
| 145 QuicPacketHeader header; | |
| 146 if (!ProcessPacketHeader(&header, packet)) { | |
| 147 DLOG(WARNING) << "Unable to process header."; | |
| 148 return RaiseError(QUIC_INVALID_PACKET_HEADER); | |
| 149 } | |
| 150 | |
| 151 if (!visitor_->OnPacketHeader(header)) { | |
| 152 reader_.reset(NULL); | |
| 153 return true; | |
| 154 } | |
| 155 | |
| 156 if (packet.length() > kMaxPacketSize) { | |
| 157 DLOG(WARNING) << "Packet too large: " << packet.length(); | |
| 158 return RaiseError(QUIC_PACKET_TOO_LARGE); | |
| 159 } | |
| 160 | |
| 161 // Handle the payload. | |
| 162 if ((header.flags & PACKET_FLAGS_FEC) == 0) { | |
| 163 if (header.fec_group != 0) { | |
| 164 StringPiece payload = reader_->PeekRemainingPayload(); | |
| 165 visitor_->OnFecProtectedPayload(payload); | |
| 166 } | |
| 167 if (!ProcessFragmentData()) { | |
| 168 DLOG(WARNING) << "Unable to process fragment data."; | |
| 169 return false; | |
| 170 } | |
| 171 } else { | |
| 172 QuicFecData fec_data; | |
| 173 fec_data.fec_group = header.fec_group; | |
| 174 if (!reader_->ReadUInt48( | |
| 175 &fec_data.first_protected_packet_sequence_number)) { | |
| 176 set_detailed_error("Unable to read first protected packet."); | |
| 177 return false; | |
| 178 } | |
| 179 | |
| 180 fec_data.redundancy = reader_->ReadRemainingPayload(); | |
| 181 visitor_->OnFecData(fec_data); | |
| 182 } | |
| 183 | |
| 184 visitor_->OnPacketComplete(); | |
| 185 reader_.reset(NULL); | |
|
jar (doing other things)
2012/10/14 23:04:38
I wasn't clear about when you wanted to delete rea
Ryan Hamilton
2012/10/15 21:22:08
I believe it is dropped everywhere. Note the DCHE
jar (doing other things)
2012/10/15 23:54:32
There are a bunch of early returns that don't *see
Ryan Hamilton
2012/10/16 00:03:56
You're talking about this, right:
158 retur
Ryan Hamilton
2012/10/16 16:46:47
Looks like 166 and 177 do not RaiseError. I'll fi
| |
| 186 return true; | |
| 187 } | |
| 188 | |
| 189 bool QuicFramer::ProcessRevivedPacket(const IPEndPoint& peer_address, | |
| 190 const QuicPacketHeader& header, | |
| 191 StringPiece payload) { | |
| 192 DCHECK(!reader_.get()); | |
| 193 | |
| 194 visitor_->OnPacket(peer_address); | |
| 195 | |
| 196 visitor_->OnPacketHeader(header); | |
| 197 | |
| 198 if (payload.length() > kMaxPacketSize) { | |
| 199 set_detailed_error("Revived packet too large."); | |
| 200 return RaiseError(QUIC_PACKET_TOO_LARGE); | |
| 201 } | |
| 202 | |
| 203 reader_.reset(new QuicDataReader(payload.data(), payload.length())); | |
| 204 if (!ProcessFragmentData()) { | |
| 205 DLOG(WARNING) << "Unable to process fragment data."; | |
|
jar (doing other things)
2012/10/14 23:04:38
This appears to be the only path where reader_ is
Ryan Hamilton
2012/10/15 21:22:08
I believe it is dropped here because RaiseError is
| |
| 206 return false; | |
| 207 } | |
| 208 | |
| 209 visitor_->OnPacketComplete(); | |
| 210 reader_.reset(NULL); | |
| 211 return true; | |
| 212 } | |
| 213 | |
| 214 bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, | |
| 215 QuicDataWriter* writer) { | |
| 216 // ConnectionHeader | |
| 217 if (!writer->WriteUInt64(header.guid)) { | |
| 218 return false; | |
| 219 } | |
| 220 | |
| 221 if (!writer->WriteUInt48(header.packet_sequence_number)) { | |
| 222 return false; | |
| 223 } | |
| 224 | |
| 225 if (!writer->WriteBytes(&header.retransmission_count, 1)) { | |
| 226 return false; | |
| 227 } | |
| 228 | |
| 229 // CongestionMonitoredHeader | |
| 230 if (!writer->WriteUInt64(header.transmission_time)) { | |
| 231 return false; | |
| 232 } | |
| 233 | |
| 234 uint8 flags = static_cast<uint8>(header.flags); | |
| 235 if (!writer->WriteBytes(&flags, 1)) { | |
| 236 return false; | |
| 237 } | |
| 238 | |
| 239 if (!writer->WriteBytes(&header.fec_group, 1)) { | |
| 240 return false; | |
| 241 } | |
| 242 | |
| 243 return true; | |
| 244 } | |
| 245 | |
| 246 bool QuicFramer::ProcessPacketHeader(QuicPacketHeader* header, | |
| 247 const QuicEncryptedPacket& packet) { | |
| 248 LOG(INFO) << "here!"; | |
| 249 // ConnectionHeader | |
| 250 if (!reader_->ReadUInt64(&header->guid)) { | |
| 251 set_detailed_error("Unable to read GUID."); | |
| 252 return false; | |
| 253 } | |
| 254 | |
| 255 LOG(INFO) << "here!"; | |
| 256 if (!reader_->ReadUInt48(&header->packet_sequence_number)) { | |
| 257 set_detailed_error("Unable to read sequence number."); | |
| 258 return false; | |
| 259 } | |
| 260 | |
| 261 LOG(INFO) << "here!"; | |
| 262 if (!reader_->ReadBytes(&header->retransmission_count, 1)) { | |
| 263 set_detailed_error("Unable to read retransmission count."); | |
| 264 return false; | |
| 265 } | |
| 266 | |
| 267 // CongestionMonitoredHeader | |
| 268 LOG(INFO) << "here!"; | |
| 269 if (!reader_->ReadUInt64(&header->transmission_time)) { | |
| 270 set_detailed_error("Unable to read transmission time."); | |
| 271 return false; | |
| 272 } | |
| 273 | |
| 274 unsigned char flags; | |
| 275 LOG(INFO) << "here!"; | |
| 276 if (!reader_->ReadBytes(&flags, 1)) { | |
| 277 set_detailed_error("Unable to read flags."); | |
| 278 return false; | |
| 279 } | |
| 280 | |
| 281 LOG(INFO) << "here!"; | |
| 282 if (flags > PACKET_FLAGS_MAX) { | |
| 283 set_detailed_error("Illegal flags value."); | |
| 284 return false; | |
| 285 } | |
| 286 | |
| 287 LOG(INFO) << "here!"; | |
| 288 header->flags = static_cast<QuicPacketFlags>(flags); | |
| 289 | |
| 290 LOG(INFO) << "here!"; | |
| 291 if (!DecryptPayload(packet)) { | |
| 292 DLOG(WARNING) << "Unable to decrypt payload."; | |
| 293 return RaiseError(QUIC_DECRYPTION_FAILURE); | |
| 294 } | |
| 295 | |
| 296 LOG(INFO) << "here!"; | |
| 297 if (!reader_->ReadBytes(&header->fec_group, 1)) { | |
| 298 set_detailed_error("Unable to read fec group."); | |
| 299 return false; | |
| 300 } | |
| 301 | |
| 302 LOG(INFO) << "done!"; | |
| 303 return true; | |
| 304 } | |
| 305 | |
| 306 bool QuicFramer::ProcessFragmentData() { | |
| 307 uint8 fragment_count; | |
| 308 if (!reader_->ReadBytes(&fragment_count, 1)) { | |
| 309 set_detailed_error("Unable to read fragment count."); | |
| 310 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 311 } | |
| 312 | |
| 313 for (uint8 i = 0; i < fragment_count; ++i) { | |
| 314 uint8 fragment_type; | |
| 315 if (!reader_->ReadBytes(&fragment_type, 1)) { | |
| 316 set_detailed_error("Unable to read fragment type."); | |
| 317 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 318 } | |
| 319 switch (fragment_type) { | |
| 320 case STREAM_FRAGMENT: | |
| 321 if (!ProcessStreamFragment()) { | |
| 322 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 323 } | |
| 324 break; | |
| 325 case PDU_FRAGMENT: | |
| 326 if (!ProcessPDUFragment()) { | |
| 327 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 328 } | |
| 329 break; | |
| 330 case ACK_FRAGMENT: { | |
| 331 QuicAckFragment fragment; | |
| 332 if (!ProcessAckFragment(&fragment)) { | |
| 333 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 334 } | |
| 335 break; | |
| 336 } | |
| 337 case RST_STREAM_FRAGMENT: | |
| 338 if (!ProcessRstStreamFragment()) { | |
| 339 return RaiseError(QUIC_INVALID_RST_STREAM_DATA); | |
| 340 } | |
| 341 break; | |
| 342 case CONNECTION_CLOSE_FRAGMENT: | |
| 343 if (!ProcessConnectionCloseFragment()) { | |
| 344 return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA); | |
| 345 } | |
| 346 break; | |
| 347 default: | |
| 348 set_detailed_error("Illegal fragment type."); | |
| 349 DLOG(WARNING) << "Illegal fragment type: " << (int)fragment_type; | |
| 350 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 351 } | |
| 352 } | |
| 353 | |
| 354 return true; | |
| 355 } | |
| 356 | |
| 357 bool QuicFramer::ProcessStreamFragment() { | |
| 358 QuicStreamFragment fragment; | |
| 359 if (!reader_->ReadUInt32(&fragment.stream_id)) { | |
| 360 set_detailed_error("Unable to read stream_id."); | |
| 361 return false; | |
| 362 } | |
| 363 | |
| 364 uint8 fin; | |
| 365 if (!reader_->ReadBytes(&fin, 1)) { | |
| 366 set_detailed_error("Unable to read fin."); | |
| 367 return false; | |
| 368 } | |
| 369 if (fin > 1) { | |
| 370 return false; | |
|
jar (doing other things)
2012/10/14 23:04:38
nit: perhaps set detailed error?
Ryan Hamilton
2012/10/15 21:22:08
Done. I assume this code path will change at some
| |
| 371 } | |
| 372 fragment.fin = (fin == 1); | |
| 373 | |
| 374 if (!reader_->ReadUInt64(&fragment.offset)) { | |
| 375 set_detailed_error("Unable to read offset."); | |
| 376 return false; | |
| 377 } | |
| 378 | |
| 379 if (!reader_->ReadStringPiece16(&fragment.data)) { | |
| 380 set_detailed_error("Unable to read fragment data."); | |
| 381 return false; | |
| 382 } | |
| 383 | |
| 384 visitor_->OnStreamFragment(fragment); | |
| 385 return true; | |
| 386 } | |
| 387 | |
| 388 bool QuicFramer::ProcessPDUFragment() { | |
| 389 return false; | |
| 390 } | |
| 391 | |
| 392 bool QuicFramer::ProcessAckFragment(QuicAckFragment* fragment) { | |
| 393 if (!reader_->ReadUInt48(&fragment->received_info.largest_received)) { | |
| 394 set_detailed_error("Unable to read largest received."); | |
| 395 return false; | |
| 396 } | |
| 397 | |
| 398 if (!reader_->ReadUInt64(&fragment->received_info.time_received)) { | |
| 399 set_detailed_error("Unable to read time received."); | |
| 400 return false; | |
| 401 } | |
| 402 | |
| 403 uint8 num_unacked_packets; | |
| 404 if (!reader_->ReadBytes(&num_unacked_packets, 1)) { | |
| 405 set_detailed_error("Unable to read num unacked packets."); | |
| 406 return false; | |
| 407 } | |
| 408 | |
| 409 for (int i = 0; i < num_unacked_packets; ++i) { | |
| 410 QuicPacketSequenceNumber sequence_number; | |
| 411 if (!reader_->ReadUInt48(&sequence_number)) { | |
| 412 set_detailed_error("Unable to read sequence number in unacked packets."); | |
| 413 return false; | |
| 414 } | |
| 415 fragment->received_info.missing_packets.insert(sequence_number); | |
| 416 } | |
| 417 | |
| 418 if (!reader_->ReadUInt48(&fragment->sent_info.least_unacked)) { | |
| 419 set_detailed_error("Unable to read least unacked."); | |
| 420 return false; | |
| 421 } | |
| 422 | |
| 423 uint8 num_non_retransmiting_packets; | |
| 424 if (!reader_->ReadBytes(&num_non_retransmiting_packets, 1)) { | |
| 425 set_detailed_error("Unable to read num non-retransmitting."); | |
| 426 return false; | |
| 427 } | |
| 428 for (uint8 i = 0; i < num_non_retransmiting_packets; ++i) { | |
| 429 QuicPacketSequenceNumber sequence_number; | |
| 430 if (!reader_->ReadUInt48(&sequence_number)) { | |
| 431 set_detailed_error( | |
| 432 "Unable to read sequence number in non-retransmitting."); | |
| 433 return false; | |
| 434 } | |
| 435 fragment->sent_info.non_retransmiting.insert(sequence_number); | |
| 436 } | |
| 437 | |
| 438 uint8 congestion_info_type; | |
| 439 if (!reader_->ReadBytes(&congestion_info_type, 1)) { | |
| 440 set_detailed_error("Unable to read congestion info type."); | |
| 441 return false; | |
| 442 } | |
| 443 fragment->congestion_info.type = | |
| 444 static_cast<CongestionFeedbackType>(congestion_info_type); | |
| 445 | |
| 446 switch (fragment->congestion_info.type) { | |
| 447 case kNone: | |
| 448 break; | |
| 449 case kInterArrival: { | |
| 450 CongestionFeedbackMessageInterArrival* inter_arrival = | |
| 451 &fragment->congestion_info.inter_arrival; | |
| 452 if (!reader_->ReadUInt16( | |
| 453 &inter_arrival->accumulated_number_of_lost_packets)) { | |
| 454 set_detailed_error( | |
| 455 "Unable to read accumulated number of lost packets."); | |
| 456 return false; | |
| 457 } | |
| 458 if (!reader_->ReadBytes(&inter_arrival->offset_time, 2)) { | |
| 459 set_detailed_error("Unable to read offset time."); | |
| 460 return false; | |
| 461 } | |
| 462 if (!reader_->ReadUInt16(&inter_arrival->delta_time)) { | |
| 463 set_detailed_error("Unable to read delta time."); | |
| 464 return false; | |
| 465 } | |
| 466 break; | |
| 467 } | |
| 468 case kFixRate: { | |
| 469 CongestionFeedbackMessageFixRate* fix_rate = | |
| 470 &fragment->congestion_info.fix_rate; | |
| 471 if (!reader_->ReadUInt32(&fix_rate->bitrate_in_bytes_per_second)) { | |
| 472 set_detailed_error("Unable to read bitrate."); | |
| 473 return false; | |
| 474 } | |
| 475 break; | |
| 476 } | |
| 477 case kTCP: { | |
| 478 CongestionFeedbackMessageTCP* tcp = &fragment->congestion_info.tcp; | |
| 479 if (!reader_->ReadUInt16(&tcp->accumulated_number_of_lost_packets)) { | |
| 480 set_detailed_error( | |
| 481 "Unable to read accumulated number of lost packets."); | |
| 482 return false; | |
| 483 } | |
| 484 if (!reader_->ReadUInt16(&tcp->receive_window)) { | |
| 485 set_detailed_error("Unable to read receive window."); | |
| 486 return false; | |
| 487 } | |
| 488 break; | |
| 489 } | |
| 490 default: | |
| 491 set_detailed_error("Illegal congestion info type."); | |
| 492 DLOG(WARNING) << "Illegal congestion info type: " | |
| 493 << fragment->congestion_info.type; | |
| 494 return RaiseError(QUIC_INVALID_FRAGMENT_DATA); | |
| 495 } | |
| 496 | |
| 497 visitor_->OnAckFragment(*fragment); | |
| 498 return true; | |
| 499 } | |
| 500 | |
| 501 bool QuicFramer::ProcessRstStreamFragment() { | |
| 502 QuicRstStreamFragment fragment; | |
| 503 if (!reader_->ReadUInt32(&fragment.stream_id)) { | |
| 504 set_detailed_error("Unable to read stream_id."); | |
| 505 return false; | |
| 506 } | |
| 507 | |
| 508 if (!reader_->ReadUInt64(&fragment.offset)) { | |
| 509 set_detailed_error("Unable to read offset in rst fragment."); | |
| 510 return false; | |
| 511 } | |
| 512 | |
| 513 uint32 details; | |
| 514 if (!reader_->ReadUInt32(&details)) { | |
| 515 set_detailed_error("Unable to read rst stream details."); | |
| 516 return false; | |
| 517 } | |
| 518 fragment.details = static_cast<QuicErrorCode>(details); | |
| 519 | |
| 520 visitor_->OnRstStreamFragment(fragment); | |
| 521 return true; | |
| 522 } | |
| 523 | |
| 524 bool QuicFramer::ProcessConnectionCloseFragment() { | |
| 525 QuicConnectionCloseFragment fragment; | |
| 526 | |
| 527 uint32 details; | |
| 528 if (!reader_->ReadUInt32(&details)) { | |
| 529 set_detailed_error("Unable to read connection close details."); | |
| 530 return false; | |
| 531 } | |
| 532 fragment.details = static_cast<QuicErrorCode>(details); | |
| 533 | |
| 534 if (!ProcessAckFragment(&fragment.ack_fragment)) { | |
| 535 DLOG(WARNING) << "Unable to process ack fragment."; | |
| 536 return false; | |
| 537 } | |
| 538 | |
| 539 visitor_->OnConnectionCloseFragment(fragment); | |
| 540 return true; | |
| 541 } | |
| 542 | |
| 543 void QuicFramer::WriteTransmissionTime(QuicTransmissionTime time, | |
| 544 QuicPacket* packet) { | |
| 545 QuicDataWriter::WriteUint64ToBuffer( | |
| 546 time, packet->mutable_data() + kTransmissionTimeOffset); | |
| 547 } | |
| 548 | |
| 549 QuicEncryptedPacket* QuicFramer::EncryptPacket(const QuicPacket& packet) { | |
| 550 scoped_ptr<QuicData> out(encrypter_->Encrypt(packet.AssociatedData(), | |
| 551 packet.Plaintext())); | |
| 552 if (out.get() == NULL) { | |
| 553 RaiseError(QUIC_ENCRYPTION_FAILURE); | |
| 554 return NULL; | |
| 555 } | |
| 556 size_t len = kStartOfEncryptedData + out->length(); | |
| 557 char* buffer = new char[len]; | |
| 558 // TODO(rch): eliminate this buffer copy by passing in a buffer to Encrypt(). | |
| 559 memcpy(buffer, packet.data(), kStartOfEncryptedData); | |
| 560 memcpy(buffer + kStartOfEncryptedData, out->data(), out->length()); | |
| 561 return new QuicEncryptedPacket(buffer, len, true); | |
| 562 } | |
| 563 | |
| 564 size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) { | |
| 565 return encrypter_->GetMaxPlaintextSize(ciphertext_size); | |
| 566 } | |
| 567 | |
| 568 bool QuicFramer::DecryptPayload(const QuicEncryptedPacket& packet) { | |
| 569 LOG(INFO) << "here!"; | |
| 570 StringPiece encrypted; | |
| 571 if (!reader_->ReadStringPiece(&encrypted, reader_->BytesRemaining())) { | |
| 572 return false; | |
| 573 } | |
| 574 DCHECK(decrypter_.get() != NULL); | |
| 575 LOG(INFO) << "here!"; | |
| 576 decrypted_.reset(decrypter_->Decrypt(packet.AssociatedData(), encrypted)); | |
| 577 if (decrypted_.get() == NULL) { | |
| 578 return false; | |
| 579 } | |
| 580 | |
| 581 reader_.reset(new QuicDataReader(decrypted_->data(), decrypted_->length())); | |
| 582 return true; | |
| 583 } | |
| 584 | |
| 585 size_t QuicFramer::ComputeFragmentPayloadLength(const QuicFragment& fragment) { | |
| 586 size_t len = 0; | |
| 587 switch (fragment.type) { | |
| 588 case STREAM_FRAGMENT: | |
| 589 len += 4; // stream id | |
|
jar (doing other things)
2012/10/14 23:04:38
nit: IMO, much better would be mostly sizeof(named
Ryan Hamilton
2012/10/15 21:22:08
This is not guaranteed to work because the in-memo
| |
| 590 len += 1; // fin | |
| 591 len += 8; // offset | |
| 592 len += 2; // space for the 16 bit length | |
| 593 len += fragment.stream_fragment->data.size(); | |
| 594 break; | |
| 595 case PDU_FRAGMENT: | |
| 596 DLOG(INFO) << "PDU_FRAGMENT not yet supported"; | |
| 597 break; // Need to support this eventually :> | |
| 598 case ACK_FRAGMENT: { | |
| 599 const QuicAckFragment& ack = *fragment.ack_fragment; | |
| 600 len += 6; // largest received packet sequence number | |
| 601 len += 8; // time delta | |
| 602 len += 1; // num missing packets | |
| 603 len += 6 * ack.received_info.missing_packets.size(); | |
| 604 len += 6; // least packet sequence number awaiting an ack | |
| 605 len += 1; // num non retransmitting packets | |
| 606 len += 6 * ack.sent_info.non_retransmiting.size(); | |
| 607 len += 1; // congestion control type | |
| 608 switch (ack.congestion_info.type) { | |
| 609 case kNone: | |
| 610 break; | |
| 611 case kInterArrival: | |
| 612 len += 6; | |
| 613 break; | |
| 614 case kFixRate: | |
| 615 len += 4; | |
| 616 break; | |
| 617 case kTCP: | |
| 618 len += 4; | |
| 619 break; | |
| 620 default: | |
| 621 set_detailed_error("Illegal feedback type."); | |
| 622 DLOG(INFO) << "Illegal feedback type: " << ack.congestion_info.type; | |
| 623 break; | |
| 624 } | |
| 625 break; | |
| 626 } | |
| 627 case RST_STREAM_FRAGMENT: | |
| 628 len += 4; // stream id | |
| 629 len += 8; // offset | |
| 630 len += 4; // details | |
| 631 break; | |
| 632 case CONNECTION_CLOSE_FRAGMENT: | |
| 633 len += 4; // details | |
| 634 len += ComputeFragmentPayloadLength( | |
| 635 QuicFragment(&fragment.connection_close_fragment->ack_fragment)); | |
| 636 break; | |
| 637 default: | |
| 638 set_detailed_error("Illegal fragment type."); | |
| 639 DLOG(INFO) << "Illegal fragment type: " << fragment.type; | |
| 640 break; | |
| 641 } | |
| 642 return len; | |
| 643 } | |
| 644 | |
| 645 bool QuicFramer::AppendStreamFragmentPayload( | |
| 646 const QuicStreamFragment& fragment, | |
| 647 QuicDataWriter* writer) { | |
| 648 if (!writer->WriteUInt32(fragment.stream_id)) { | |
| 649 return false; | |
| 650 } | |
| 651 if (!writer->WriteUInt8(fragment.fin)) { | |
| 652 return false; | |
| 653 } | |
| 654 if (!writer->WriteUInt64(fragment.offset)) { | |
| 655 return false; | |
| 656 } | |
| 657 if (!writer->WriteUInt16(fragment.data.size())) { | |
| 658 return false; | |
| 659 } | |
| 660 if (!writer->WriteBytes(fragment.data.data(), | |
| 661 fragment.data.size())) { | |
| 662 return false; | |
| 663 } | |
| 664 return true; | |
| 665 } | |
| 666 | |
| 667 bool QuicFramer::AppendAckFragmentPayload( | |
| 668 const QuicAckFragment& fragment, | |
| 669 QuicDataWriter* writer) { | |
| 670 if (!writer->WriteUInt48(fragment.received_info.largest_received)) { | |
| 671 return false; | |
| 672 } | |
| 673 if (!writer->WriteUInt64(fragment.received_info.time_received)) { | |
| 674 return false; | |
| 675 } | |
| 676 | |
| 677 size_t num_unacked_packets = fragment.received_info.missing_packets.size(); | |
| 678 if (!writer->WriteBytes(&num_unacked_packets, 1)) { | |
| 679 return false; | |
| 680 } | |
| 681 | |
| 682 hash_set<QuicPacketSequenceNumber>::const_iterator it = | |
| 683 fragment.received_info.missing_packets.begin(); | |
| 684 for (; it != fragment.received_info.missing_packets.end(); ++it) { | |
| 685 if (!writer->WriteUInt48(*it)) { | |
| 686 return false; | |
| 687 } | |
| 688 } | |
| 689 | |
| 690 if (!writer->WriteUInt48(fragment.sent_info.least_unacked)) { | |
| 691 return false; | |
| 692 } | |
| 693 | |
| 694 size_t num_non_retransmiting_packets = | |
| 695 fragment.sent_info.non_retransmiting.size(); | |
| 696 if (!writer->WriteBytes(&num_non_retransmiting_packets, 1)) { | |
| 697 return false; | |
| 698 } | |
| 699 | |
| 700 it = fragment.sent_info.non_retransmiting.begin(); | |
| 701 while (it != fragment.sent_info.non_retransmiting.end()) { | |
| 702 if (!writer->WriteUInt48(*it)) { | |
| 703 return false; | |
| 704 } | |
| 705 ++it; | |
| 706 } | |
| 707 | |
| 708 if (!writer->WriteBytes(&fragment.congestion_info.type, 1)) { | |
| 709 return false; | |
| 710 } | |
| 711 | |
| 712 switch (fragment.congestion_info.type) { | |
| 713 case kNone: | |
| 714 break; | |
| 715 case kInterArrival: { | |
| 716 const CongestionFeedbackMessageInterArrival& inter_arrival = | |
| 717 fragment.congestion_info.inter_arrival; | |
| 718 if (!writer->WriteUInt16( | |
| 719 inter_arrival.accumulated_number_of_lost_packets)) { | |
| 720 return false; | |
| 721 } | |
| 722 if (!writer->WriteBytes(&inter_arrival.offset_time, 2)) { | |
| 723 return false; | |
| 724 } | |
| 725 if (!writer->WriteUInt16(inter_arrival.delta_time)) { | |
| 726 return false; | |
| 727 } | |
| 728 break; | |
| 729 } | |
| 730 case kFixRate: { | |
| 731 const CongestionFeedbackMessageFixRate& fix_rate = | |
| 732 fragment.congestion_info.fix_rate; | |
| 733 if (!writer->WriteUInt32(fix_rate.bitrate_in_bytes_per_second)) { | |
| 734 return false; | |
| 735 } | |
| 736 break; | |
| 737 } | |
| 738 case kTCP: { | |
| 739 const CongestionFeedbackMessageTCP& tcp = fragment.congestion_info.tcp; | |
| 740 if (!writer->WriteUInt16(tcp.accumulated_number_of_lost_packets)) { | |
| 741 return false; | |
| 742 } | |
| 743 if (!writer->WriteUInt16(tcp.receive_window)) { | |
| 744 return false; | |
| 745 } | |
| 746 break; | |
| 747 } | |
| 748 default: | |
| 749 return false; | |
| 750 } | |
| 751 | |
| 752 return true; | |
| 753 } | |
| 754 | |
| 755 bool QuicFramer::AppendRstStreamFragmentPayload( | |
| 756 const QuicRstStreamFragment& fragment, | |
| 757 QuicDataWriter* writer) { | |
| 758 if (!writer->WriteUInt32(fragment.stream_id)) { | |
| 759 return false; | |
| 760 } | |
| 761 if (!writer->WriteUInt64(fragment.offset)) { | |
| 762 return false; | |
| 763 } | |
| 764 | |
| 765 uint32 details = static_cast<uint32>(fragment.details); | |
| 766 if (!writer->WriteUInt32(details)) { | |
| 767 return false; | |
| 768 } | |
| 769 return true; | |
| 770 } | |
| 771 | |
| 772 bool QuicFramer::AppendConnectionCloseFragmentPayload( | |
| 773 const QuicConnectionCloseFragment& fragment, | |
| 774 QuicDataWriter* writer) { | |
| 775 uint32 details = static_cast<uint32>(fragment.details); | |
| 776 if (!writer->WriteUInt32(details)) { | |
| 777 return false; | |
| 778 } | |
| 779 AppendAckFragmentPayload(fragment.ack_fragment, writer); | |
| 780 return true; | |
| 781 } | |
| 782 | |
| 783 bool QuicFramer::RaiseError(QuicErrorCode error) { | |
| 784 DLOG(INFO) << detailed_error_; | |
| 785 set_error(error); | |
| 786 visitor_->OnError(this); | |
| 787 reader_.reset(NULL); | |
| 788 return false; | |
| 789 } | |
| 790 | |
| 791 } // namespace net | |
| OLD | NEW |