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 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't | 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't |
6 // constantly adding and subtracting header sizes; this is ugly and error- | 6 // constantly adding and subtracting header sizes; this is ugly and error- |
7 // prone. | 7 // prone. |
8 | 8 |
9 #include "net/spdy/spdy_framer.h" | 9 #include "net/spdy/spdy_framer.h" |
10 | 10 |
(...skipping 28 matching lines...) Expand all Loading... |
39 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize)) | 39 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize)) |
40 {} | 40 {} |
41 const uLong v2_dictionary_id; | 41 const uLong v2_dictionary_id; |
42 const uLong v3_dictionary_id; | 42 const uLong v3_dictionary_id; |
43 }; | 43 }; |
44 | 44 |
45 // Adler ID for the SPDY header compressor dictionaries. Note that they are | 45 // Adler ID for the SPDY header compressor dictionaries. Note that they are |
46 // initialized lazily to avoid static initializers. | 46 // initialized lazily to avoid static initializers. |
47 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; | 47 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; |
48 | 48 |
| 49 // Used to indicate no flags in a SPDY flags field. |
| 50 const uint8 kNoFlags = 0; |
| 51 |
49 } // namespace | 52 } // namespace |
50 | 53 |
51 const int SpdyFramer::kMinSpdyVersion = 2; | 54 const int SpdyFramer::kMinSpdyVersion = 2; |
52 const int SpdyFramer::kMaxSpdyVersion = 3; | 55 const int SpdyFramer::kMaxSpdyVersion = 3; |
53 const SpdyStreamId SpdyFramer::kInvalidStream = -1; | 56 const SpdyStreamId SpdyFramer::kInvalidStream = -1; |
54 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 57 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
55 const size_t SpdyFramer::kControlFrameBufferSize = | 58 const size_t SpdyFramer::kControlFrameBufferSize = |
56 sizeof(SpdySynStreamControlFrameBlock); | 59 sizeof(SpdySynStreamControlFrameBlock); |
57 const size_t SpdyFramer::kMaxControlFrameSize = 16 * 1024; | 60 const size_t SpdyFramer::kMaxControlFrameSize = 16 * 1024; |
58 | 61 |
(...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, | 673 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, |
671 const int spdy_version, | 674 const int spdy_version, |
672 const SpdyHeaderBlock* headers) { | 675 const SpdyHeaderBlock* headers) { |
673 if (spdy_version < 3) { | 676 if (spdy_version < 3) { |
674 frame->WriteUInt16(headers->size()); // Number of headers. | 677 frame->WriteUInt16(headers->size()); // Number of headers. |
675 } else { | 678 } else { |
676 frame->WriteUInt32(headers->size()); // Number of headers. | 679 frame->WriteUInt32(headers->size()); // Number of headers. |
677 } | 680 } |
678 SpdyHeaderBlock::const_iterator it; | 681 SpdyHeaderBlock::const_iterator it; |
679 for (it = headers->begin(); it != headers->end(); ++it) { | 682 for (it = headers->begin(); it != headers->end(); ++it) { |
680 bool wrote_header; | |
681 if (spdy_version < 3) { | 683 if (spdy_version < 3) { |
682 wrote_header = frame->WriteString(it->first); | 684 frame->WriteString(it->first); |
683 wrote_header &= frame->WriteString(it->second); | 685 frame->WriteString(it->second); |
684 } else { | 686 } else { |
685 wrote_header = frame->WriteStringPiece32(it->first); | 687 frame->WriteStringPiece32(it->first); |
686 wrote_header &= frame->WriteStringPiece32(it->second); | 688 frame->WriteStringPiece32(it->second); |
687 } | 689 } |
688 DCHECK(wrote_header); | |
689 } | 690 } |
690 } | 691 } |
691 | 692 |
692 // TODO(phajdan.jr): Clean up after we no longer need | 693 // TODO(phajdan.jr): Clean up after we no longer need |
693 // to workaround http://crbug.com/139744. | 694 // to workaround http://crbug.com/139744. |
694 #if !defined(USE_SYSTEM_ZLIB) | 695 #if !defined(USE_SYSTEM_ZLIB) |
695 | 696 |
696 // These constants are used by zlib to differentiate between normal data and | 697 // These constants are used by zlib to differentiate between normal data and |
697 // cookie data. Cookie data is handled specially by zlib when compressing. | 698 // cookie data. Cookie data is handled specially by zlib when compressing. |
698 enum ZDataClass { | 699 enum ZDataClass { |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 } | 1285 } |
1285 | 1286 |
1286 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( | 1287 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( |
1287 SpdyStreamId stream_id, | 1288 SpdyStreamId stream_id, |
1288 SpdyStreamId associated_stream_id, | 1289 SpdyStreamId associated_stream_id, |
1289 SpdyPriority priority, | 1290 SpdyPriority priority, |
1290 uint8 credential_slot, | 1291 uint8 credential_slot, |
1291 SpdyControlFlags flags, | 1292 SpdyControlFlags flags, |
1292 bool compressed, | 1293 bool compressed, |
1293 const SpdyHeaderBlock* headers) { | 1294 const SpdyHeaderBlock* headers) { |
1294 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1295 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL); |
1295 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); | |
1296 | 1296 |
1297 // Find our length. | 1297 SpdySynStreamIR syn_stream(stream_id); |
1298 size_t frame_size = SpdySynStreamControlFrame::size() + | 1298 syn_stream.set_associated_to_stream_id(associated_stream_id); |
1299 GetSerializedLength(spdy_version_, headers); | 1299 syn_stream.set_priority(priority); |
1300 | 1300 syn_stream.set_slot(credential_slot); |
1301 SpdyFrameBuilder frame(SYN_STREAM, flags, spdy_version_, frame_size); | 1301 syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0); |
1302 frame.WriteUInt32(stream_id); | 1302 syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0); |
1303 frame.WriteUInt32(associated_stream_id); | 1303 // TODO(hkhalil): Avoid copy here. |
1304 // Cap as appropriate. | 1304 *(syn_stream.GetMutableNameValueBlock()) = *headers; |
1305 if (priority > GetLowestPriority()) { | |
1306 DLOG(DFATAL) << "Priority out-of-bounds."; | |
1307 priority = GetLowestPriority(); | |
1308 } | |
1309 // Priority is 2 bits for <spdy3, 3 bits otherwise. | |
1310 frame.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); | |
1311 frame.WriteUInt8((spdy_version_ < 3) ? 0 : credential_slot); | |
1312 WriteHeaderBlock(&frame, spdy_version_, headers); | |
1313 DCHECK_EQ(frame.length(), frame_size); | |
1314 | 1305 |
1315 scoped_ptr<SpdySynStreamControlFrame> syn_frame( | 1306 scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
1316 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); | 1307 reinterpret_cast<SpdySynStreamControlFrame*>( |
| 1308 SerializeSynStream(syn_stream))); |
1317 if (compressed) { | 1309 if (compressed) { |
1318 return reinterpret_cast<SpdySynStreamControlFrame*>( | 1310 return reinterpret_cast<SpdySynStreamControlFrame*>( |
1319 CompressControlFrame(*syn_frame.get(), headers)); | 1311 CompressControlFrame(*syn_frame.get(), headers)); |
1320 } | 1312 } |
1321 return syn_frame.release(); | 1313 return syn_frame.release(); |
1322 } | 1314 } |
1323 | 1315 |
| 1316 SpdySerializedFrame* SpdyFramer::SerializeSynStream( |
| 1317 const SpdySynStreamIR& syn_stream) { |
| 1318 uint8 flags = 0; |
| 1319 if (syn_stream.fin()) { |
| 1320 flags |= CONTROL_FLAG_FIN; |
| 1321 } |
| 1322 if (syn_stream.unidirectional()) { |
| 1323 flags |= CONTROL_FLAG_UNIDIRECTIONAL; |
| 1324 } |
| 1325 |
| 1326 // The size, in bytes, of this frame not including the variable-length |
| 1327 // name-value block. Calculated as: |
| 1328 // 8 (control frame header) + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) |
| 1329 const size_t kSynStreamSizeBeforeNameValueBlock = 18; |
| 1330 |
| 1331 // The size of this frame, including variable-length name-value block. |
| 1332 const size_t size = kSynStreamSizeBeforeNameValueBlock |
| 1333 + GetSerializedLength(protocol_version(), |
| 1334 &(syn_stream.name_value_block())); |
| 1335 |
| 1336 SpdyFrameBuilder builder(SYN_STREAM, flags, protocol_version(), size); |
| 1337 builder.WriteUInt32(syn_stream.stream_id()); |
| 1338 builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
| 1339 uint8 priority = syn_stream.priority(); |
| 1340 if (priority > GetLowestPriority()) { |
| 1341 DLOG(DFATAL) << "Priority out-of-bounds."; |
| 1342 priority = GetLowestPriority(); |
| 1343 } |
| 1344 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
| 1345 builder.WriteUInt8(syn_stream.slot()); |
| 1346 DCHECK_EQ(kSynStreamSizeBeforeNameValueBlock, builder.length()); |
| 1347 SerializeNameValueBlock(&builder, syn_stream); |
| 1348 |
| 1349 return builder.take(); |
| 1350 } |
| 1351 |
1324 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( | 1352 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( |
1325 SpdyStreamId stream_id, | 1353 SpdyStreamId stream_id, |
1326 SpdyControlFlags flags, | 1354 SpdyControlFlags flags, |
1327 bool compressed, | 1355 bool compressed, |
1328 const SpdyHeaderBlock* headers) { | 1356 const SpdyHeaderBlock* headers) { |
1329 DCHECK_GT(stream_id, 0u); | 1357 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN); |
1330 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | |
1331 | 1358 |
1332 // Find our length. | 1359 SpdySynReplyIR syn_reply(stream_id); |
1333 size_t frame_size = SpdySynReplyControlFrame::size() + | 1360 syn_reply.set_fin(flags & CONTROL_FLAG_FIN); |
1334 GetSerializedLength(spdy_version_, headers); | 1361 // TODO(hkhalil): Avoid copy here. |
1335 // In SPDY 2, there were 2 unused bytes before payload. | 1362 *(syn_reply.GetMutableNameValueBlock()) = *headers; |
1336 if (spdy_version_ < 3) { | |
1337 frame_size += 2; | |
1338 } | |
1339 | |
1340 SpdyFrameBuilder frame(SYN_REPLY, flags, spdy_version_, frame_size); | |
1341 frame.WriteUInt32(stream_id); | |
1342 if (spdy_version_ < 3) { | |
1343 frame.WriteUInt16(0); // Unused | |
1344 } | |
1345 WriteHeaderBlock(&frame, spdy_version_, headers); | |
1346 DCHECK_EQ(frame.length(), frame_size); | |
1347 | 1363 |
1348 scoped_ptr<SpdySynReplyControlFrame> reply_frame( | 1364 scoped_ptr<SpdySynReplyControlFrame> reply_frame( |
1349 reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); | 1365 reinterpret_cast<SpdySynReplyControlFrame*>(SerializeSynReply( |
| 1366 syn_reply))); |
1350 if (compressed) { | 1367 if (compressed) { |
1351 return reinterpret_cast<SpdySynReplyControlFrame*>( | 1368 return reinterpret_cast<SpdySynReplyControlFrame*>( |
1352 CompressControlFrame(*reply_frame.get(), headers)); | 1369 CompressControlFrame(*reply_frame.get(), headers)); |
1353 } | 1370 } |
1354 return reply_frame.release(); | 1371 return reply_frame.release(); |
1355 } | 1372 } |
1356 | 1373 |
| 1374 SpdySerializedFrame* SpdyFramer::SerializeSynReply( |
| 1375 const SpdySynReplyIR& syn_reply) { |
| 1376 uint8 flags = 0; |
| 1377 if (syn_reply.fin()) { |
| 1378 flags |= CONTROL_FLAG_FIN; |
| 1379 } |
| 1380 |
| 1381 // The size, in bytes, of this frame not including the variable-length |
| 1382 // name-value block. Calculated as: |
| 1383 // 8 (control frame header) + 4 (stream ID) |
| 1384 size_t syn_reply_size_before_name_value_block = 12; |
| 1385 // In SPDY 2, there were 2 unused bytes before payload. |
| 1386 if (protocol_version() < 3) { |
| 1387 syn_reply_size_before_name_value_block += 2; |
| 1388 } |
| 1389 |
| 1390 // The size of this frame, including variable-length name-value block. |
| 1391 size_t size = syn_reply_size_before_name_value_block |
| 1392 + GetSerializedLength(protocol_version(), |
| 1393 &(syn_reply.name_value_block())); |
| 1394 |
| 1395 SpdyFrameBuilder builder(SYN_REPLY, flags, protocol_version(), size); |
| 1396 builder.WriteUInt32(syn_reply.stream_id()); |
| 1397 if (protocol_version() < 3) { |
| 1398 builder.WriteUInt16(0); // Unused. |
| 1399 } |
| 1400 DCHECK_EQ(syn_reply_size_before_name_value_block, builder.length()); |
| 1401 SerializeNameValueBlock(&builder, syn_reply); |
| 1402 |
| 1403 return builder.take(); |
| 1404 } |
| 1405 |
1357 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream( | 1406 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream( |
1358 SpdyStreamId stream_id, | 1407 SpdyStreamId stream_id, |
1359 SpdyRstStreamStatus status) const { | 1408 SpdyRstStreamStatus status) const { |
1360 DCHECK_GT(stream_id, 0u); | 1409 SpdyRstStreamIR rst_stream(stream_id, status); |
1361 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1410 return reinterpret_cast<SpdyRstStreamControlFrame*>( |
1362 DCHECK_NE(status, RST_STREAM_INVALID); | 1411 SerializeRstStream(rst_stream)); |
1363 DCHECK_LT(status, RST_STREAM_NUM_STATUS_CODES); | 1412 } |
1364 | 1413 |
1365 size_t frame_size = SpdyRstStreamControlFrame::size(); | 1414 SpdySerializedFrame* SpdyFramer::SerializeRstStream( |
1366 SpdyFrameBuilder frame(RST_STREAM, CONTROL_FLAG_NONE, spdy_version_, | 1415 const SpdyRstStreamIR& rst_stream) const { |
1367 frame_size); | 1416 // Size of our RST_STREAM frame. Calculated as: |
1368 frame.WriteUInt32(stream_id); | 1417 // 8 (control frame header) + 4 (stream id) + 4 (status code) |
1369 frame.WriteUInt32(status); | 1418 const size_t kRstStreamFrameSize = 16; |
1370 DCHECK_EQ(frame.length(), frame_size); | 1419 |
1371 return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take()); | 1420 SpdyFrameBuilder builder(RST_STREAM, |
| 1421 kNoFlags, |
| 1422 protocol_version(), |
| 1423 kRstStreamFrameSize); |
| 1424 builder.WriteUInt32(rst_stream.stream_id()); |
| 1425 builder.WriteUInt32(rst_stream.status()); |
| 1426 DCHECK_EQ(kRstStreamFrameSize, builder.length()); |
| 1427 return builder.take(); |
1372 } | 1428 } |
1373 | 1429 |
1374 SpdySettingsControlFrame* SpdyFramer::CreateSettings( | 1430 SpdySettingsControlFrame* SpdyFramer::CreateSettings( |
1375 const SettingsMap& values) const { | 1431 const SettingsMap& values) const { |
1376 size_t frame_size = SpdySettingsControlFrame::size() + 8 * values.size(); | 1432 SpdySettingsIR settings; |
1377 SpdyFrameBuilder frame(SETTINGS, CONTROL_FLAG_NONE, spdy_version_, | |
1378 frame_size); | |
1379 frame.WriteUInt32(values.size()); | |
1380 for (SettingsMap::const_iterator it = values.begin(); | 1433 for (SettingsMap::const_iterator it = values.begin(); |
1381 it != values.end(); | 1434 it != values.end(); |
1382 it++) { | 1435 ++it) { |
1383 SettingsFlagsAndId flags_and_id(it->second.first, it->first); | 1436 settings.AddSetting(it->first, |
1384 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(spdy_version_); | 1437 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0, |
1385 frame.WriteBytes(&id_and_flags_wire, 4); | 1438 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0, |
1386 frame.WriteUInt32(it->second.second); | 1439 it->second.second); |
1387 } | 1440 } |
1388 DCHECK_EQ(frame.length(), frame_size); | 1441 return reinterpret_cast<SpdySettingsControlFrame*>( |
1389 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); | 1442 SerializeSettings(settings)); |
| 1443 } |
| 1444 |
| 1445 SpdySerializedFrame* SpdyFramer::SerializeSettings( |
| 1446 const SpdySettingsIR& settings) const { |
| 1447 uint8 flags = 0; |
| 1448 if (settings.clear_settings()) { |
| 1449 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; |
| 1450 } |
| 1451 const SpdySettingsIR::ValueMap* values = &(settings.values()); |
| 1452 |
| 1453 // Size, in bytes, of this SETTINGS frame not including the IDs and values |
| 1454 // from the variable-length value block. Calculated as: |
| 1455 // 8 (control frame header) + 4 (number of ID/value pairs) |
| 1456 const size_t kSettingsSizeWithoutValues = 12; |
| 1457 // Size, in bytes, of this SETTINGS frame. |
| 1458 const size_t size = kSettingsSizeWithoutValues + (values->size() * 8); |
| 1459 |
| 1460 SpdyFrameBuilder builder(SETTINGS, flags, protocol_version(), size); |
| 1461 builder.WriteUInt32(values->size()); |
| 1462 DCHECK_EQ(kSettingsSizeWithoutValues, builder.length()); |
| 1463 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); |
| 1464 it != values->end(); |
| 1465 ++it) { |
| 1466 uint8 setting_flags = 0; |
| 1467 if (it->second.persist_value) { |
| 1468 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; |
| 1469 } |
| 1470 if (it->second.persisted) { |
| 1471 setting_flags |= SETTINGS_FLAG_PERSISTED; |
| 1472 } |
| 1473 SettingsFlagsAndId flags_and_id(setting_flags, it->first); |
| 1474 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); |
| 1475 builder.WriteBytes(&id_and_flags_wire, 4); |
| 1476 builder.WriteUInt32(it->second.value); |
| 1477 } |
| 1478 DCHECK_EQ(size, builder.length()); |
| 1479 return builder.take(); |
1390 } | 1480 } |
1391 | 1481 |
1392 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { | 1482 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { |
1393 size_t frame_size = SpdyPingControlFrame::size(); | 1483 SpdyPingIR ping(unique_id); |
1394 SpdyFrameBuilder frame(PING, CONTROL_FLAG_NONE, spdy_version_, frame_size); | 1484 return reinterpret_cast<SpdyPingControlFrame*>(SerializePing(ping)); |
1395 frame.WriteUInt32(unique_id); | 1485 } |
1396 DCHECK_EQ(frame.length(), frame_size); | 1486 |
1397 return reinterpret_cast<SpdyPingControlFrame*>(frame.take()); | 1487 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
| 1488 // Size, in bytes, of this PING frame. Calculated as: |
| 1489 // 8 (control frame header) + 4 (id) |
| 1490 const size_t kPingSize = 12; |
| 1491 SpdyFrameBuilder builder(PING, 0, protocol_version(), kPingSize); |
| 1492 builder.WriteUInt32(ping.id()); |
| 1493 DCHECK_EQ(kPingSize, builder.length()); |
| 1494 return builder.take(); |
1398 } | 1495 } |
1399 | 1496 |
1400 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( | 1497 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( |
1401 SpdyStreamId last_accepted_stream_id, | 1498 SpdyStreamId last_accepted_stream_id, |
1402 SpdyGoAwayStatus status) const { | 1499 SpdyGoAwayStatus status) const { |
1403 DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); | 1500 SpdyGoAwayIR goaway(last_accepted_stream_id, status); |
1404 | 1501 return reinterpret_cast<SpdyGoAwayControlFrame*>(SerializeGoAway(goaway)); |
1405 // SPDY 2 GOAWAY frames are 4 bytes smaller than in SPDY 3. We account for | 1502 } |
1406 // this difference via a separate offset variable, since | 1503 |
1407 // SpdyGoAwayControlFrame::size() returns the SPDY 3 size. | 1504 SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
1408 const size_t goaway_offset = (protocol_version() < 3) ? 4 : 0; | 1505 const SpdyGoAwayIR& goaway) const { |
1409 size_t frame_size = SpdyGoAwayControlFrame::size() - goaway_offset; | 1506 // Size, in bytes, of this GOAWAY frame. Calculated as: |
1410 SpdyFrameBuilder frame(GOAWAY, CONTROL_FLAG_NONE, spdy_version_, frame_size); | 1507 // 8 (control frame header) + 4 (last good stream id) |
1411 frame.WriteUInt32(last_accepted_stream_id); | 1508 size_t size = 12; |
| 1509 // SPDY 3+ GOAWAY frames also contain a status. |
1412 if (protocol_version() >= 3) { | 1510 if (protocol_version() >= 3) { |
1413 frame.WriteUInt32(status); | 1511 size += 4; |
1414 } | 1512 } |
1415 DCHECK_EQ(frame.length(), frame_size); | 1513 SpdyFrameBuilder builder(GOAWAY, 0, protocol_version(), size); |
1416 return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); | 1514 builder.WriteUInt32(goaway.last_good_stream_id()); |
| 1515 if (protocol_version() >= 3) { |
| 1516 builder.WriteUInt32(goaway.status()); |
| 1517 } |
| 1518 DCHECK_EQ(size, builder.length()); |
| 1519 return builder.take(); |
1417 } | 1520 } |
1418 | 1521 |
1419 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders( | 1522 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders( |
1420 SpdyStreamId stream_id, | 1523 SpdyStreamId stream_id, |
1421 SpdyControlFlags flags, | 1524 SpdyControlFlags flags, |
1422 bool compressed, | 1525 bool compressed, |
1423 const SpdyHeaderBlock* headers) { | 1526 const SpdyHeaderBlock* header_block) { |
1424 // Basically the same as CreateSynReply(). | 1527 // Basically the same as CreateSynReply(). |
1425 DCHECK_GT(stream_id, 0u); | 1528 DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN)); |
1426 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1529 |
1427 | 1530 SpdyHeadersIR headers(stream_id); |
1428 // Find our length. | 1531 headers.set_fin(flags & CONTROL_FLAG_FIN); |
1429 size_t frame_size = SpdyHeadersControlFrame::size() + | 1532 // TODO(hkhalil): Avoid copy here. |
1430 GetSerializedLength(spdy_version_, headers); | 1533 *(headers.GetMutableNameValueBlock()) = *header_block; |
1431 // In SPDY 2, there were 2 unused bytes before payload. | |
1432 if (spdy_version_ < 3) { | |
1433 frame_size += 2; | |
1434 } | |
1435 | |
1436 SpdyFrameBuilder frame(HEADERS, flags, spdy_version_, frame_size); | |
1437 frame.WriteUInt32(stream_id); | |
1438 if (spdy_version_ < 3) { | |
1439 frame.WriteUInt16(0); // Unused | |
1440 } | |
1441 WriteHeaderBlock(&frame, spdy_version_, headers); | |
1442 DCHECK_EQ(frame.length(), frame_size); | |
1443 | 1534 |
1444 scoped_ptr<SpdyHeadersControlFrame> headers_frame( | 1535 scoped_ptr<SpdyHeadersControlFrame> headers_frame( |
1445 reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); | 1536 reinterpret_cast<SpdyHeadersControlFrame*>(SerializeHeaders(headers))); |
1446 if (compressed) { | 1537 if (compressed) { |
1447 return reinterpret_cast<SpdyHeadersControlFrame*>( | 1538 return reinterpret_cast<SpdyHeadersControlFrame*>( |
1448 CompressControlFrame(*headers_frame.get(), headers)); | 1539 CompressControlFrame(*headers_frame.get(), |
| 1540 headers.GetMutableNameValueBlock())); |
1449 } | 1541 } |
1450 return headers_frame.release(); | 1542 return headers_frame.release(); |
1451 } | 1543 } |
1452 | 1544 |
| 1545 SpdySerializedFrame* SpdyFramer::SerializeHeaders( |
| 1546 const SpdyHeadersIR& headers) { |
| 1547 uint8 flags = 0; |
| 1548 if (headers.fin()) { |
| 1549 flags |= CONTROL_FLAG_FIN; |
| 1550 } |
| 1551 |
| 1552 // The size, in bytes, of this frame not including the variable-length |
| 1553 // name-value block. Calculated as: |
| 1554 // 8 (control frame header) + 4 (stream ID) |
| 1555 size_t headers_size_before_name_value_block = 12; |
| 1556 // In SPDY 2, there were 2 unused bytes before payload. |
| 1557 if (protocol_version() < 3) { |
| 1558 headers_size_before_name_value_block += 2; |
| 1559 } |
| 1560 |
| 1561 // The size of this frame, including variable-length name-value block. |
| 1562 size_t size = headers_size_before_name_value_block |
| 1563 + GetSerializedLength(protocol_version(), |
| 1564 &(headers.name_value_block())); |
| 1565 |
| 1566 SpdyFrameBuilder builder(HEADERS, flags, protocol_version(), size); |
| 1567 builder.WriteUInt32(headers.stream_id()); |
| 1568 if (protocol_version() < 3) { |
| 1569 builder.WriteUInt16(0); // Unused. |
| 1570 } |
| 1571 DCHECK_EQ(headers_size_before_name_value_block, builder.length()); |
| 1572 |
| 1573 SerializeNameValueBlock(&builder, headers); |
| 1574 DCHECK_EQ(size, builder.length()); |
| 1575 |
| 1576 return builder.take(); |
| 1577 } |
| 1578 |
1453 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( | 1579 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( |
1454 SpdyStreamId stream_id, | 1580 SpdyStreamId stream_id, |
1455 uint32 delta_window_size) const { | 1581 uint32 delta_window_size) const { |
1456 DCHECK_GT(stream_id, 0u); | 1582 SpdyWindowUpdateIR window_update(stream_id, delta_window_size); |
1457 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1583 return reinterpret_cast<SpdyWindowUpdateControlFrame*>( |
1458 DCHECK_GT(delta_window_size, 0u); | 1584 SerializeWindowUpdate(window_update)); |
1459 DCHECK_LE(delta_window_size, | 1585 } |
1460 static_cast<uint32>(kSpdyStreamMaximumWindowSize)); | 1586 |
1461 | 1587 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( |
1462 size_t frame_size = SpdyWindowUpdateControlFrame::size(); | 1588 const SpdyWindowUpdateIR& window_update) const { |
1463 SpdyFrameBuilder frame(WINDOW_UPDATE, CONTROL_FLAG_NONE, spdy_version_, | 1589 // Size, in bytes, of this WINDOW_UPDATE frame. Calculated as: |
1464 frame_size); | 1590 // 8 (control frame header) + 4 (stream id) + 4 (delta) |
1465 frame.WriteUInt32(stream_id); | 1591 const size_t kWindowUpdateSize = 16; |
1466 frame.WriteUInt32(delta_window_size); | 1592 |
1467 DCHECK_EQ(frame.length(), frame_size); | 1593 SpdyFrameBuilder builder(WINDOW_UPDATE, |
1468 return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take()); | 1594 kNoFlags, |
1469 } | 1595 protocol_version(), |
1470 | 1596 kWindowUpdateSize); |
| 1597 builder.WriteUInt32(window_update.stream_id()); |
| 1598 builder.WriteUInt32(window_update.delta()); |
| 1599 DCHECK_EQ(kWindowUpdateSize, builder.length()); |
| 1600 return builder.take(); |
| 1601 } |
| 1602 |
| 1603 // TODO(hkhalil): Gut with SpdyCredential removal. |
1471 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( | 1604 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( |
1472 const SpdyCredential& credential) const { | 1605 const SpdyCredential& credential) const { |
1473 // Calculate the size of the frame by adding the size of the | 1606 SpdyCredentialIR credential_ir(credential.slot); |
1474 // variable length data to the size of the fixed length data. | 1607 credential_ir.set_proof(credential.proof); |
1475 size_t frame_size = SpdyCredentialControlFrame::size() + | |
1476 credential.proof.length(); | |
1477 DCHECK_EQ(SpdyCredentialControlFrame::size(), 14u); | |
1478 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); | 1608 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); |
1479 cert != credential.certs.end(); | 1609 cert != credential.certs.end(); |
1480 ++cert) { | 1610 ++cert) { |
1481 frame_size += sizeof(uint32); // size of the cert_length field | 1611 credential_ir.AddCertificate(*cert); |
1482 frame_size += cert->length(); // size of the cert_data field | 1612 } |
1483 } | 1613 return reinterpret_cast<SpdyCredentialControlFrame*>( |
1484 | 1614 SerializeCredential(credential_ir)); |
1485 SpdyFrameBuilder frame(CREDENTIAL, CONTROL_FLAG_NONE, spdy_version_, | 1615 } |
1486 frame_size); | 1616 |
1487 frame.WriteUInt16(credential.slot); | 1617 SpdySerializedFrame* SpdyFramer::SerializeCredential( |
1488 frame.WriteUInt32(credential.proof.size()); | 1618 const SpdyCredentialIR& credential) const { |
1489 frame.WriteBytes(credential.proof.c_str(), credential.proof.size()); | 1619 size_t size = 8; // Room for frame header. |
1490 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); | 1620 size += 2; // Room for slot. |
1491 cert != credential.certs.end(); | 1621 size += 4 + credential.proof().length(); // Room for proof. |
1492 ++cert) { | 1622 for (SpdyCredentialIR::CertificateList::const_iterator it = |
1493 frame.WriteUInt32(cert->length()); | 1623 credential.certificates()->begin(); |
1494 frame.WriteBytes(cert->c_str(), cert->length()); | 1624 it != credential.certificates()->end(); |
1495 } | 1625 ++it) { |
1496 DCHECK_EQ(frame.length(), frame_size); | 1626 size += 4 + it->length(); // Room for certificate. |
1497 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); | 1627 } |
| 1628 |
| 1629 SpdyFrameBuilder builder(CREDENTIAL, 0, protocol_version(), size); |
| 1630 builder.WriteUInt16(credential.slot()); |
| 1631 builder.WriteStringPiece32(credential.proof()); |
| 1632 for (SpdyCredentialIR::CertificateList::const_iterator it = |
| 1633 credential.certificates()->begin(); |
| 1634 it != credential.certificates()->end(); |
| 1635 ++it) { |
| 1636 builder.WriteStringPiece32(*it); |
| 1637 } |
| 1638 DCHECK_EQ(size, builder.length()); |
| 1639 return builder.take(); |
1498 } | 1640 } |
1499 | 1641 |
1500 SpdyDataFrame* SpdyFramer::CreateDataFrame( | 1642 SpdyDataFrame* SpdyFramer::CreateDataFrame( |
1501 SpdyStreamId stream_id, | 1643 SpdyStreamId stream_id, const char* data, |
1502 const char* data, | |
1503 uint32 len, SpdyDataFlags flags) const { | 1644 uint32 len, SpdyDataFlags flags) const { |
1504 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1645 DCHECK_EQ(0, flags & (!DATA_FLAG_FIN)); |
1505 size_t frame_size = SpdyDataFrame::size() + len; | 1646 |
1506 SpdyFrameBuilder frame(stream_id, flags, frame_size); | 1647 SpdyDataIR data_ir(stream_id, base::StringPiece(data, len)); |
1507 frame.WriteBytes(data, len); | 1648 data_ir.set_fin(flags & DATA_FLAG_FIN); |
1508 DCHECK_EQ(frame.length(), frame_size); | 1649 return reinterpret_cast<SpdyDataFrame*>(SerializeData(data_ir)); |
1509 return reinterpret_cast<SpdyDataFrame*>(frame.take()); | 1650 } |
| 1651 |
| 1652 SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const { |
| 1653 // Size, in bytes, of this DATA frame. Calculated as: |
| 1654 // 4 (stream id) + 1 (flags) + 3 (length) + payload length |
| 1655 const size_t size = 8 + data.data().length(); |
| 1656 |
| 1657 SpdyDataFlags flags = DATA_FLAG_NONE; |
| 1658 if (data.fin()) { |
| 1659 flags = DATA_FLAG_FIN; |
| 1660 } |
| 1661 |
| 1662 SpdyFrameBuilder builder(data.stream_id(), flags, size); |
| 1663 builder.WriteBytes(data.data().data(), data.data().length()); |
| 1664 DCHECK_EQ(size, builder.length()); |
| 1665 return builder.take(); |
1510 } | 1666 } |
1511 | 1667 |
1512 // The following compression setting are based on Brian Olson's analysis. See | 1668 // The following compression setting are based on Brian Olson's analysis. See |
1513 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 | 1669 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 |
1514 // for more details. | 1670 // for more details. |
1515 #if defined(USE_SYSTEM_ZLIB) | 1671 #if defined(USE_SYSTEM_ZLIB) |
1516 // System zlib is not expected to have workaround for http://crbug.com/139744, | 1672 // System zlib is not expected to have workaround for http://crbug.com/139744, |
1517 // so disable compression in that case. | 1673 // so disable compression in that case. |
1518 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. | 1674 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. |
1519 static const int kCompressorLevel = 0; | 1675 static const int kCompressorLevel = 0; |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1905 case PING: | 2061 case PING: |
1906 case GOAWAY: | 2062 case GOAWAY: |
1907 case CREDENTIAL: | 2063 case CREDENTIAL: |
1908 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy | 2064 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy |
1909 break; | 2065 break; |
1910 } | 2066 } |
1911 } | 2067 } |
1912 return stream_id; | 2068 return stream_id; |
1913 } | 2069 } |
1914 | 2070 |
1915 void SpdyFramer::set_enable_compression(bool value) { | 2071 void SpdyFramer::SerializeNameValueBlock( |
1916 enable_compression_ = value; | 2072 SpdyFrameBuilder* builder, |
| 2073 const SpdyFrameWithNameValueBlockIR& frame) const { |
| 2074 const SpdyNameValueBlock* name_value_block = &(frame.name_value_block()); |
| 2075 |
| 2076 // Serialize number of headers. |
| 2077 if (protocol_version() < 3) { |
| 2078 builder->WriteUInt16(name_value_block->size()); |
| 2079 } else { |
| 2080 builder->WriteUInt32(name_value_block->size()); |
| 2081 } |
| 2082 |
| 2083 // Serialize each header. |
| 2084 for (SpdyHeaderBlock::const_iterator it = name_value_block->begin(); |
| 2085 it != name_value_block->end(); |
| 2086 ++it) { |
| 2087 if (protocol_version() < 3) { |
| 2088 builder->WriteString(it->first); |
| 2089 builder->WriteString(it->second); |
| 2090 } else { |
| 2091 builder->WriteStringPiece32(it->first); |
| 2092 builder->WriteStringPiece32(it->second); |
| 2093 } |
| 2094 } |
1917 } | 2095 } |
1918 | 2096 |
1919 } // namespace net | 2097 } // namespace net |
OLD | NEW |