Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: net/spdy/spdy_framer.cc

Issue 12220116: Refactor in preparation for SPDY 4, part 1. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Windows compile errors Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_protocol.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_protocol.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698