| 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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 state_ = SPDY_RESET; | 148 state_ = SPDY_RESET; |
| 149 previous_state_ = SPDY_RESET; | 149 previous_state_ = SPDY_RESET; |
| 150 error_code_ = SPDY_NO_ERROR; | 150 error_code_ = SPDY_NO_ERROR; |
| 151 remaining_data_ = 0; | 151 remaining_data_ = 0; |
| 152 remaining_control_payload_ = 0; | 152 remaining_control_payload_ = 0; |
| 153 remaining_control_header_ = 0; | 153 remaining_control_header_ = 0; |
| 154 current_frame_len_ = 0; | 154 current_frame_len_ = 0; |
| 155 settings_scratch_.Reset(); | 155 settings_scratch_.Reset(); |
| 156 } | 156 } |
| 157 | 157 |
| 158 size_t SpdyFramer::GetControlFrameMinimumSize() const { |
| 159 // Size, in bytes, of the control frame header. Future versions of SPDY |
| 160 // will likely vary this, so we allow for the flexibility of a function call |
| 161 // for this value as opposed to a constant. |
| 162 return 8; |
| 163 } |
| 164 |
| 165 size_t SpdyFramer::GetSynStreamMinimumSize() const { |
| 166 // Size, in bytes, of a SYN_STREAM frame not including the variable-length |
| 167 // name-value block. Calculated as: |
| 168 // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) |
| 169 return GetControlFrameMinimumSize() + 10; |
| 170 } |
| 171 |
| 172 size_t SpdyFramer::GetSynReplyMinimumSize() const { |
| 173 // Size, in bytes, of a SYN_REPLY frame not including the variable-length |
| 174 // name-value block. Calculated as: |
| 175 // control frame header + 4 (stream ID) |
| 176 size_t size = GetControlFrameMinimumSize() + 4; |
| 177 |
| 178 // In SPDY 2, there were 2 unused bytes before payload. |
| 179 if (protocol_version() < 3) { |
| 180 size += 2; |
| 181 } |
| 182 |
| 183 return size; |
| 184 } |
| 185 |
| 186 size_t SpdyFramer::GetRstStreamSize() const { |
| 187 // Size, in bytes, of a RST_STREAM frame. Calculated as: |
| 188 // control frame header + 4 (stream id) + 4 (status code) |
| 189 return GetControlFrameMinimumSize() + 8; |
| 190 } |
| 191 |
| 192 size_t SpdyFramer::GetSettingsMinimumSize() const { |
| 193 // Size, in bytes, of a SETTINGS frame not including the IDs and values |
| 194 // from the variable-length value block. Calculated as: |
| 195 // control frame header + 4 (number of ID/value pairs) |
| 196 return GetControlFrameMinimumSize() + 4; |
| 197 } |
| 198 |
| 199 size_t SpdyFramer::GetPingSize() const { |
| 200 // Size, in bytes, of this PING frame. Calculated as: |
| 201 // control frame header + 4 (id) |
| 202 return GetControlFrameMinimumSize() + 4; |
| 203 } |
| 204 |
| 205 size_t SpdyFramer::GetGoAwaySize() const { |
| 206 // Size, in bytes, of this GOAWAY frame. Calculated as: |
| 207 // control frame header + 4 (last good stream id) |
| 208 size_t size = GetControlFrameMinimumSize() + 4; |
| 209 |
| 210 // SPDY 3+ GOAWAY frames also contain a status. |
| 211 if (protocol_version() >= 3) { |
| 212 size += 4; |
| 213 } |
| 214 |
| 215 return size; |
| 216 } |
| 217 |
| 218 size_t SpdyFramer::GetHeadersMinimumSize() const { |
| 219 // Size, in bytes, of a HEADERS frame not including the variable-length |
| 220 // name-value block. Calculated as: |
| 221 // control frame header + 4 (stream ID) |
| 222 size_t size = GetControlFrameMinimumSize() + 4; |
| 223 |
| 224 // In SPDY 2, there were 2 unused bytes before payload. |
| 225 if (protocol_version() < 3) { |
| 226 size += 2; |
| 227 } |
| 228 |
| 229 return size; |
| 230 } |
| 231 |
| 232 size_t SpdyFramer::GetWindowUpdateSize() const { |
| 233 // Size, in bytes, of this WINDOW_UPDATE frame. Calculated as: |
| 234 // control frame header + 4 (stream id) + 4 (delta) |
| 235 return GetControlFrameMinimumSize() + 8; |
| 236 } |
| 237 |
| 238 size_t SpdyFramer::GetCredentialMinimumSize() const { |
| 239 // Size, in bytes, of a CREDENTIAL frame sans variable-length certificate list |
| 240 // and proof. Calculated as: |
| 241 // control frame header + 2 (slot) |
| 242 return GetControlFrameMinimumSize() + 2; |
| 243 } |
| 244 |
| 158 const char* SpdyFramer::StateToString(int state) { | 245 const char* SpdyFramer::StateToString(int state) { |
| 159 switch (state) { | 246 switch (state) { |
| 160 case SPDY_ERROR: | 247 case SPDY_ERROR: |
| 161 return "ERROR"; | 248 return "ERROR"; |
| 162 case SPDY_DONE: | 249 case SPDY_DONE: |
| 163 return "DONE"; | 250 return "DONE"; |
| 164 case SPDY_AUTO_RESET: | 251 case SPDY_AUTO_RESET: |
| 165 return "AUTO_RESET"; | 252 return "AUTO_RESET"; |
| 166 case SPDY_RESET: | 253 case SPDY_RESET: |
| 167 return "RESET"; | 254 return "RESET"; |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 if (current_control_frame.type() == NOOP) { | 548 if (current_control_frame.type() == NOOP) { |
| 462 DLOG(INFO) << "NOOP control frame found. Ignoring."; | 549 DLOG(INFO) << "NOOP control frame found. Ignoring."; |
| 463 CHANGE_STATE(SPDY_AUTO_RESET); | 550 CHANGE_STATE(SPDY_AUTO_RESET); |
| 464 return; | 551 return; |
| 465 } | 552 } |
| 466 | 553 |
| 467 // Do some sanity checking on the control frame sizes. | 554 // Do some sanity checking on the control frame sizes. |
| 468 switch (current_control_frame.type()) { | 555 switch (current_control_frame.type()) { |
| 469 case SYN_STREAM: | 556 case SYN_STREAM: |
| 470 if (current_control_frame.length() < | 557 if (current_control_frame.length() < |
| 471 SpdySynStreamControlFrame::size() - SpdyControlFrame::kHeaderSize) { | 558 GetSynStreamMinimumSize() - SpdyControlFrame::kHeaderSize) { |
| 472 set_error(SPDY_INVALID_CONTROL_FRAME); | 559 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 473 } else if (current_control_frame.flags() & | 560 } else if (current_control_frame.flags() & |
| 474 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { | 561 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { |
| 475 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 562 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 476 } | 563 } |
| 477 break; | 564 break; |
| 478 case SYN_REPLY: | 565 case SYN_REPLY: |
| 479 if (current_control_frame.length() < | 566 if (current_control_frame.length() < |
| 480 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize) { | 567 GetSynReplyMinimumSize() - SpdyControlFrame::kHeaderSize) { |
| 481 set_error(SPDY_INVALID_CONTROL_FRAME); | 568 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 482 } else if (current_control_frame.flags() & ~CONTROL_FLAG_FIN) { | 569 } else if (current_control_frame.flags() & ~CONTROL_FLAG_FIN) { |
| 483 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 570 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 484 } | 571 } |
| 485 break; | 572 break; |
| 486 case RST_STREAM: | 573 case RST_STREAM: |
| 487 if (current_control_frame.length() != | 574 if (current_control_frame.length() != |
| 488 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize) { | 575 GetRstStreamSize() - SpdyFrame::kHeaderSize) { |
| 489 set_error(SPDY_INVALID_CONTROL_FRAME); | 576 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 490 } else if (current_control_frame.flags() != 0) { | 577 } else if (current_control_frame.flags() != 0) { |
| 491 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 578 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 492 } | 579 } |
| 493 break; | 580 break; |
| 494 case SETTINGS: | 581 case SETTINGS: |
| 495 // Make sure that we have an integral number of 8-byte key/value pairs, | 582 // Make sure that we have an integral number of 8-byte key/value pairs, |
| 496 // plus a 4-byte length field. | 583 // plus a 4-byte length field. |
| 497 if (current_control_frame.length() < | 584 if (current_control_frame.length() < |
| 498 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize || | 585 GetSettingsMinimumSize() - SpdyControlFrame::kHeaderSize || |
| 499 (current_control_frame.length() % 8 != 4)) { | 586 (current_control_frame.length() % 8 != 4)) { |
| 500 DLOG(WARNING) << "Invalid length for SETTINGS frame: " | 587 DLOG(WARNING) << "Invalid length for SETTINGS frame: " |
| 501 << current_control_frame.length(); | 588 << current_control_frame.length(); |
| 502 set_error(SPDY_INVALID_CONTROL_FRAME); | 589 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 503 } else if (current_control_frame.flags() & | 590 } else if (current_control_frame.flags() & |
| 504 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { | 591 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { |
| 505 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 592 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 506 } | 593 } |
| 507 break; | 594 break; |
| 508 case GOAWAY: | 595 case GOAWAY: |
| 509 { | 596 { |
| 510 // SPDY 2 GOAWAY frames are 4 bytes smaller than in SPDY 3. We account | 597 if (current_control_frame.length() != |
| 511 // for this difference via a separate offset variable, since | 598 GetGoAwaySize() - SpdyFrame::kHeaderSize) { |
| 512 // SpdyGoAwayControlFrame::size() returns the SPDY 3 size. | |
| 513 const size_t goaway_offset = (protocol_version() < 3) ? 4 : 0; | |
| 514 if (current_control_frame.length() + goaway_offset != | |
| 515 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize) { | |
| 516 set_error(SPDY_INVALID_CONTROL_FRAME); | 599 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 517 } else if (current_control_frame.flags() != 0) { | 600 } else if (current_control_frame.flags() != 0) { |
| 518 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 601 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 519 } | 602 } |
| 520 break; | 603 break; |
| 521 } | 604 } |
| 522 case HEADERS: | 605 case HEADERS: |
| 523 if (current_control_frame.length() < | 606 if (current_control_frame.length() < |
| 524 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize) { | 607 GetHeadersMinimumSize() - SpdyControlFrame::kHeaderSize) { |
| 525 set_error(SPDY_INVALID_CONTROL_FRAME); | 608 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 526 } else if (current_control_frame.flags() & ~CONTROL_FLAG_FIN) { | 609 } else if (current_control_frame.flags() & ~CONTROL_FLAG_FIN) { |
| 527 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 610 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 528 } | 611 } |
| 529 break; | 612 break; |
| 530 case WINDOW_UPDATE: | 613 case WINDOW_UPDATE: |
| 531 if (current_control_frame.length() != | 614 if (current_control_frame.length() != |
| 532 SpdyWindowUpdateControlFrame::size() - | 615 GetWindowUpdateSize() - SpdyControlFrame::kHeaderSize) { |
| 533 SpdyControlFrame::kHeaderSize) { | |
| 534 set_error(SPDY_INVALID_CONTROL_FRAME); | 616 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 535 } else if (current_control_frame.flags() != 0) { | 617 } else if (current_control_frame.flags() != 0) { |
| 536 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 618 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 537 } | 619 } |
| 538 break; | 620 break; |
| 539 case PING: | 621 case PING: |
| 540 if (current_control_frame.length() != | 622 if (current_control_frame.length() != |
| 541 SpdyPingControlFrame::size() - SpdyControlFrame::kHeaderSize) { | 623 GetPingSize() - SpdyControlFrame::kHeaderSize) { |
| 542 set_error(SPDY_INVALID_CONTROL_FRAME); | 624 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 543 } else if (current_control_frame.flags() != 0) { | 625 } else if (current_control_frame.flags() != 0) { |
| 544 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 626 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 545 } | 627 } |
| 546 break; | 628 break; |
| 547 case CREDENTIAL: | 629 case CREDENTIAL: |
| 548 if (current_control_frame.length() < | 630 if (current_control_frame.length() < |
| 549 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize) { | 631 GetCredentialMinimumSize() - SpdyControlFrame::kHeaderSize) { |
| 550 set_error(SPDY_INVALID_CONTROL_FRAME); | 632 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 551 } else if (current_control_frame.flags() != 0) { | 633 } else if (current_control_frame.flags() != 0) { |
| 552 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 634 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 553 } | 635 } |
| 554 break; | 636 break; |
| 555 default: | 637 default: |
| 556 LOG(WARNING) << "Valid " << display_protocol_ | 638 LOG(WARNING) << "Valid " << display_protocol_ |
| 557 << " control frame with unhandled type: " | 639 << " control frame with unhandled type: " |
| 558 << current_control_frame.type(); | 640 << current_control_frame.type(); |
| 559 DLOG(FATAL); | 641 DLOG(FATAL); |
| (...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 SpdySerializedFrame* SpdyFramer::SerializeSynStream( | 1398 SpdySerializedFrame* SpdyFramer::SerializeSynStream( |
| 1317 const SpdySynStreamIR& syn_stream) { | 1399 const SpdySynStreamIR& syn_stream) { |
| 1318 uint8 flags = 0; | 1400 uint8 flags = 0; |
| 1319 if (syn_stream.fin()) { | 1401 if (syn_stream.fin()) { |
| 1320 flags |= CONTROL_FLAG_FIN; | 1402 flags |= CONTROL_FLAG_FIN; |
| 1321 } | 1403 } |
| 1322 if (syn_stream.unidirectional()) { | 1404 if (syn_stream.unidirectional()) { |
| 1323 flags |= CONTROL_FLAG_UNIDIRECTIONAL; | 1405 flags |= CONTROL_FLAG_UNIDIRECTIONAL; |
| 1324 } | 1406 } |
| 1325 | 1407 |
| 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. | 1408 // The size of this frame, including variable-length name-value block. |
| 1332 const size_t size = kSynStreamSizeBeforeNameValueBlock | 1409 const size_t size = GetSynStreamMinimumSize() |
| 1333 + GetSerializedLength(protocol_version(), | 1410 + GetSerializedLength(protocol_version(), |
| 1334 &(syn_stream.name_value_block())); | 1411 &(syn_stream.name_value_block())); |
| 1335 | 1412 |
| 1336 SpdyFrameBuilder builder(SYN_STREAM, flags, protocol_version(), size); | 1413 SpdyFrameBuilder builder(SYN_STREAM, flags, protocol_version(), size); |
| 1337 builder.WriteUInt32(syn_stream.stream_id()); | 1414 builder.WriteUInt32(syn_stream.stream_id()); |
| 1338 builder.WriteUInt32(syn_stream.associated_to_stream_id()); | 1415 builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
| 1339 uint8 priority = syn_stream.priority(); | 1416 uint8 priority = syn_stream.priority(); |
| 1340 if (priority > GetLowestPriority()) { | 1417 if (priority > GetLowestPriority()) { |
| 1341 DLOG(DFATAL) << "Priority out-of-bounds."; | 1418 DLOG(DFATAL) << "Priority out-of-bounds."; |
| 1342 priority = GetLowestPriority(); | 1419 priority = GetLowestPriority(); |
| 1343 } | 1420 } |
| 1344 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); | 1421 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
| 1345 builder.WriteUInt8(syn_stream.slot()); | 1422 builder.WriteUInt8(syn_stream.slot()); |
| 1346 DCHECK_EQ(kSynStreamSizeBeforeNameValueBlock, builder.length()); | 1423 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); |
| 1347 SerializeNameValueBlock(&builder, syn_stream); | 1424 SerializeNameValueBlock(&builder, syn_stream); |
| 1348 | 1425 |
| 1349 return builder.take(); | 1426 return builder.take(); |
| 1350 } | 1427 } |
| 1351 | 1428 |
| 1352 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( | 1429 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( |
| 1353 SpdyStreamId stream_id, | 1430 SpdyStreamId stream_id, |
| 1354 SpdyControlFlags flags, | 1431 SpdyControlFlags flags, |
| 1355 bool compressed, | 1432 bool compressed, |
| 1356 const SpdyHeaderBlock* headers) { | 1433 const SpdyHeaderBlock* headers) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1371 return reply_frame.release(); | 1448 return reply_frame.release(); |
| 1372 } | 1449 } |
| 1373 | 1450 |
| 1374 SpdySerializedFrame* SpdyFramer::SerializeSynReply( | 1451 SpdySerializedFrame* SpdyFramer::SerializeSynReply( |
| 1375 const SpdySynReplyIR& syn_reply) { | 1452 const SpdySynReplyIR& syn_reply) { |
| 1376 uint8 flags = 0; | 1453 uint8 flags = 0; |
| 1377 if (syn_reply.fin()) { | 1454 if (syn_reply.fin()) { |
| 1378 flags |= CONTROL_FLAG_FIN; | 1455 flags |= CONTROL_FLAG_FIN; |
| 1379 } | 1456 } |
| 1380 | 1457 |
| 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. | 1458 // The size of this frame, including variable-length name-value block. |
| 1391 size_t size = syn_reply_size_before_name_value_block | 1459 size_t size = GetSynReplyMinimumSize() |
| 1392 + GetSerializedLength(protocol_version(), | 1460 + GetSerializedLength(protocol_version(), |
| 1393 &(syn_reply.name_value_block())); | 1461 &(syn_reply.name_value_block())); |
| 1394 | 1462 |
| 1395 SpdyFrameBuilder builder(SYN_REPLY, flags, protocol_version(), size); | 1463 SpdyFrameBuilder builder(SYN_REPLY, flags, protocol_version(), size); |
| 1396 builder.WriteUInt32(syn_reply.stream_id()); | 1464 builder.WriteUInt32(syn_reply.stream_id()); |
| 1397 if (protocol_version() < 3) { | 1465 if (protocol_version() < 3) { |
| 1398 builder.WriteUInt16(0); // Unused. | 1466 builder.WriteUInt16(0); // Unused. |
| 1399 } | 1467 } |
| 1400 DCHECK_EQ(syn_reply_size_before_name_value_block, builder.length()); | 1468 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); |
| 1401 SerializeNameValueBlock(&builder, syn_reply); | 1469 SerializeNameValueBlock(&builder, syn_reply); |
| 1402 | 1470 |
| 1403 return builder.take(); | 1471 return builder.take(); |
| 1404 } | 1472 } |
| 1405 | 1473 |
| 1406 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream( | 1474 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream( |
| 1407 SpdyStreamId stream_id, | 1475 SpdyStreamId stream_id, |
| 1408 SpdyRstStreamStatus status) const { | 1476 SpdyRstStreamStatus status) const { |
| 1409 SpdyRstStreamIR rst_stream(stream_id, status); | 1477 SpdyRstStreamIR rst_stream(stream_id, status); |
| 1410 return reinterpret_cast<SpdyRstStreamControlFrame*>( | 1478 return reinterpret_cast<SpdyRstStreamControlFrame*>( |
| 1411 SerializeRstStream(rst_stream)); | 1479 SerializeRstStream(rst_stream)); |
| 1412 } | 1480 } |
| 1413 | 1481 |
| 1414 SpdySerializedFrame* SpdyFramer::SerializeRstStream( | 1482 SpdySerializedFrame* SpdyFramer::SerializeRstStream( |
| 1415 const SpdyRstStreamIR& rst_stream) const { | 1483 const SpdyRstStreamIR& rst_stream) const { |
| 1416 // Size of our RST_STREAM frame. Calculated as: | |
| 1417 // 8 (control frame header) + 4 (stream id) + 4 (status code) | |
| 1418 const size_t kRstStreamFrameSize = 16; | |
| 1419 | |
| 1420 SpdyFrameBuilder builder(RST_STREAM, | 1484 SpdyFrameBuilder builder(RST_STREAM, |
| 1421 kNoFlags, | 1485 kNoFlags, |
| 1422 protocol_version(), | 1486 protocol_version(), |
| 1423 kRstStreamFrameSize); | 1487 GetRstStreamSize()); |
| 1424 builder.WriteUInt32(rst_stream.stream_id()); | 1488 builder.WriteUInt32(rst_stream.stream_id()); |
| 1425 builder.WriteUInt32(rst_stream.status()); | 1489 builder.WriteUInt32(rst_stream.status()); |
| 1426 DCHECK_EQ(kRstStreamFrameSize, builder.length()); | 1490 DCHECK_EQ(GetRstStreamSize(), builder.length()); |
| 1427 return builder.take(); | 1491 return builder.take(); |
| 1428 } | 1492 } |
| 1429 | 1493 |
| 1430 SpdySettingsControlFrame* SpdyFramer::CreateSettings( | 1494 SpdySettingsControlFrame* SpdyFramer::CreateSettings( |
| 1431 const SettingsMap& values) const { | 1495 const SettingsMap& values) const { |
| 1432 SpdySettingsIR settings; | 1496 SpdySettingsIR settings; |
| 1433 for (SettingsMap::const_iterator it = values.begin(); | 1497 for (SettingsMap::const_iterator it = values.begin(); |
| 1434 it != values.end(); | 1498 it != values.end(); |
| 1435 ++it) { | 1499 ++it) { |
| 1436 settings.AddSetting(it->first, | 1500 settings.AddSetting(it->first, |
| 1437 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0, | 1501 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0, |
| 1438 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0, | 1502 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0, |
| 1439 it->second.second); | 1503 it->second.second); |
| 1440 } | 1504 } |
| 1441 return reinterpret_cast<SpdySettingsControlFrame*>( | 1505 return reinterpret_cast<SpdySettingsControlFrame*>( |
| 1442 SerializeSettings(settings)); | 1506 SerializeSettings(settings)); |
| 1443 } | 1507 } |
| 1444 | 1508 |
| 1445 SpdySerializedFrame* SpdyFramer::SerializeSettings( | 1509 SpdySerializedFrame* SpdyFramer::SerializeSettings( |
| 1446 const SpdySettingsIR& settings) const { | 1510 const SpdySettingsIR& settings) const { |
| 1447 uint8 flags = 0; | 1511 uint8 flags = 0; |
| 1448 if (settings.clear_settings()) { | 1512 if (settings.clear_settings()) { |
| 1449 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; | 1513 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; |
| 1450 } | 1514 } |
| 1451 const SpdySettingsIR::ValueMap* values = &(settings.values()); | 1515 const SpdySettingsIR::ValueMap* values = &(settings.values()); |
| 1452 | 1516 |
| 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. | 1517 // Size, in bytes, of this SETTINGS frame. |
| 1458 const size_t size = kSettingsSizeWithoutValues + (values->size() * 8); | 1518 const size_t size = GetSettingsMinimumSize() + (values->size() * 8); |
| 1459 | 1519 |
| 1460 SpdyFrameBuilder builder(SETTINGS, flags, protocol_version(), size); | 1520 SpdyFrameBuilder builder(SETTINGS, flags, protocol_version(), size); |
| 1461 builder.WriteUInt32(values->size()); | 1521 builder.WriteUInt32(values->size()); |
| 1462 DCHECK_EQ(kSettingsSizeWithoutValues, builder.length()); | 1522 DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); |
| 1463 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); | 1523 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); |
| 1464 it != values->end(); | 1524 it != values->end(); |
| 1465 ++it) { | 1525 ++it) { |
| 1466 uint8 setting_flags = 0; | 1526 uint8 setting_flags = 0; |
| 1467 if (it->second.persist_value) { | 1527 if (it->second.persist_value) { |
| 1468 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; | 1528 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; |
| 1469 } | 1529 } |
| 1470 if (it->second.persisted) { | 1530 if (it->second.persisted) { |
| 1471 setting_flags |= SETTINGS_FLAG_PERSISTED; | 1531 setting_flags |= SETTINGS_FLAG_PERSISTED; |
| 1472 } | 1532 } |
| 1473 SettingsFlagsAndId flags_and_id(setting_flags, it->first); | 1533 SettingsFlagsAndId flags_and_id(setting_flags, it->first); |
| 1474 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); | 1534 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); |
| 1475 builder.WriteBytes(&id_and_flags_wire, 4); | 1535 builder.WriteBytes(&id_and_flags_wire, 4); |
| 1476 builder.WriteUInt32(it->second.value); | 1536 builder.WriteUInt32(it->second.value); |
| 1477 } | 1537 } |
| 1478 DCHECK_EQ(size, builder.length()); | 1538 DCHECK_EQ(size, builder.length()); |
| 1479 return builder.take(); | 1539 return builder.take(); |
| 1480 } | 1540 } |
| 1481 | 1541 |
| 1482 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { | 1542 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { |
| 1483 SpdyPingIR ping(unique_id); | 1543 SpdyPingIR ping(unique_id); |
| 1484 return reinterpret_cast<SpdyPingControlFrame*>(SerializePing(ping)); | 1544 return reinterpret_cast<SpdyPingControlFrame*>(SerializePing(ping)); |
| 1485 } | 1545 } |
| 1486 | 1546 |
| 1487 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { | 1547 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
| 1488 // Size, in bytes, of this PING frame. Calculated as: | 1548 SpdyFrameBuilder builder(PING, 0, protocol_version(), GetPingSize()); |
| 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()); | 1549 builder.WriteUInt32(ping.id()); |
| 1493 DCHECK_EQ(kPingSize, builder.length()); | 1550 DCHECK_EQ(GetPingSize(), builder.length()); |
| 1494 return builder.take(); | 1551 return builder.take(); |
| 1495 } | 1552 } |
| 1496 | 1553 |
| 1497 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( | 1554 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( |
| 1498 SpdyStreamId last_accepted_stream_id, | 1555 SpdyStreamId last_accepted_stream_id, |
| 1499 SpdyGoAwayStatus status) const { | 1556 SpdyGoAwayStatus status) const { |
| 1500 SpdyGoAwayIR goaway(last_accepted_stream_id, status); | 1557 SpdyGoAwayIR goaway(last_accepted_stream_id, status); |
| 1501 return reinterpret_cast<SpdyGoAwayControlFrame*>(SerializeGoAway(goaway)); | 1558 return reinterpret_cast<SpdyGoAwayControlFrame*>(SerializeGoAway(goaway)); |
| 1502 } | 1559 } |
| 1503 | 1560 |
| 1504 SpdySerializedFrame* SpdyFramer::SerializeGoAway( | 1561 SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
| 1505 const SpdyGoAwayIR& goaway) const { | 1562 const SpdyGoAwayIR& goaway) const { |
| 1506 // Size, in bytes, of this GOAWAY frame. Calculated as: | 1563 SpdyFrameBuilder builder(GOAWAY, 0, protocol_version(), GetGoAwaySize()); |
| 1507 // 8 (control frame header) + 4 (last good stream id) | |
| 1508 size_t size = 12; | |
| 1509 // SPDY 3+ GOAWAY frames also contain a status. | |
| 1510 if (protocol_version() >= 3) { | |
| 1511 size += 4; | |
| 1512 } | |
| 1513 SpdyFrameBuilder builder(GOAWAY, 0, protocol_version(), size); | |
| 1514 builder.WriteUInt32(goaway.last_good_stream_id()); | 1564 builder.WriteUInt32(goaway.last_good_stream_id()); |
| 1515 if (protocol_version() >= 3) { | 1565 if (protocol_version() >= 3) { |
| 1516 builder.WriteUInt32(goaway.status()); | 1566 builder.WriteUInt32(goaway.status()); |
| 1517 } | 1567 } |
| 1518 DCHECK_EQ(size, builder.length()); | 1568 DCHECK_EQ(GetGoAwaySize(), builder.length()); |
| 1519 return builder.take(); | 1569 return builder.take(); |
| 1520 } | 1570 } |
| 1521 | 1571 |
| 1522 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders( | 1572 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders( |
| 1523 SpdyStreamId stream_id, | 1573 SpdyStreamId stream_id, |
| 1524 SpdyControlFlags flags, | 1574 SpdyControlFlags flags, |
| 1525 bool compressed, | 1575 bool compressed, |
| 1526 const SpdyHeaderBlock* header_block) { | 1576 const SpdyHeaderBlock* header_block) { |
| 1527 // Basically the same as CreateSynReply(). | 1577 // Basically the same as CreateSynReply(). |
| 1528 DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN)); | 1578 DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1542 return headers_frame.release(); | 1592 return headers_frame.release(); |
| 1543 } | 1593 } |
| 1544 | 1594 |
| 1545 SpdySerializedFrame* SpdyFramer::SerializeHeaders( | 1595 SpdySerializedFrame* SpdyFramer::SerializeHeaders( |
| 1546 const SpdyHeadersIR& headers) { | 1596 const SpdyHeadersIR& headers) { |
| 1547 uint8 flags = 0; | 1597 uint8 flags = 0; |
| 1548 if (headers.fin()) { | 1598 if (headers.fin()) { |
| 1549 flags |= CONTROL_FLAG_FIN; | 1599 flags |= CONTROL_FLAG_FIN; |
| 1550 } | 1600 } |
| 1551 | 1601 |
| 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. | 1602 // The size of this frame, including variable-length name-value block. |
| 1562 size_t size = headers_size_before_name_value_block | 1603 size_t size = GetHeadersMinimumSize() |
| 1563 + GetSerializedLength(protocol_version(), | 1604 + GetSerializedLength(protocol_version(), |
| 1564 &(headers.name_value_block())); | 1605 &(headers.name_value_block())); |
| 1565 | 1606 |
| 1566 SpdyFrameBuilder builder(HEADERS, flags, protocol_version(), size); | 1607 SpdyFrameBuilder builder(HEADERS, flags, protocol_version(), size); |
| 1567 builder.WriteUInt32(headers.stream_id()); | 1608 builder.WriteUInt32(headers.stream_id()); |
| 1568 if (protocol_version() < 3) { | 1609 if (protocol_version() < 3) { |
| 1569 builder.WriteUInt16(0); // Unused. | 1610 builder.WriteUInt16(0); // Unused. |
| 1570 } | 1611 } |
| 1571 DCHECK_EQ(headers_size_before_name_value_block, builder.length()); | 1612 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); |
| 1572 | 1613 |
| 1573 SerializeNameValueBlock(&builder, headers); | 1614 SerializeNameValueBlock(&builder, headers); |
| 1574 DCHECK_EQ(size, builder.length()); | 1615 DCHECK_EQ(size, builder.length()); |
| 1575 | 1616 |
| 1576 return builder.take(); | 1617 return builder.take(); |
| 1577 } | 1618 } |
| 1578 | 1619 |
| 1579 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( | 1620 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( |
| 1580 SpdyStreamId stream_id, | 1621 SpdyStreamId stream_id, |
| 1581 uint32 delta_window_size) const { | 1622 uint32 delta_window_size) const { |
| 1582 SpdyWindowUpdateIR window_update(stream_id, delta_window_size); | 1623 SpdyWindowUpdateIR window_update(stream_id, delta_window_size); |
| 1583 return reinterpret_cast<SpdyWindowUpdateControlFrame*>( | 1624 return reinterpret_cast<SpdyWindowUpdateControlFrame*>( |
| 1584 SerializeWindowUpdate(window_update)); | 1625 SerializeWindowUpdate(window_update)); |
| 1585 } | 1626 } |
| 1586 | 1627 |
| 1587 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( | 1628 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( |
| 1588 const SpdyWindowUpdateIR& window_update) const { | 1629 const SpdyWindowUpdateIR& window_update) const { |
| 1589 // Size, in bytes, of this WINDOW_UPDATE frame. Calculated as: | |
| 1590 // 8 (control frame header) + 4 (stream id) + 4 (delta) | |
| 1591 const size_t kWindowUpdateSize = 16; | |
| 1592 | |
| 1593 SpdyFrameBuilder builder(WINDOW_UPDATE, | 1630 SpdyFrameBuilder builder(WINDOW_UPDATE, |
| 1594 kNoFlags, | 1631 kNoFlags, |
| 1595 protocol_version(), | 1632 protocol_version(), |
| 1596 kWindowUpdateSize); | 1633 GetWindowUpdateSize()); |
| 1597 builder.WriteUInt32(window_update.stream_id()); | 1634 builder.WriteUInt32(window_update.stream_id()); |
| 1598 builder.WriteUInt32(window_update.delta()); | 1635 builder.WriteUInt32(window_update.delta()); |
| 1599 DCHECK_EQ(kWindowUpdateSize, builder.length()); | 1636 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); |
| 1600 return builder.take(); | 1637 return builder.take(); |
| 1601 } | 1638 } |
| 1602 | 1639 |
| 1603 // TODO(hkhalil): Gut with SpdyCredential removal. | 1640 // TODO(hkhalil): Gut with SpdyCredential removal. |
| 1604 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( | 1641 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( |
| 1605 const SpdyCredential& credential) const { | 1642 const SpdyCredential& credential) const { |
| 1606 SpdyCredentialIR credential_ir(credential.slot); | 1643 SpdyCredentialIR credential_ir(credential.slot); |
| 1607 credential_ir.set_proof(credential.proof); | 1644 credential_ir.set_proof(credential.proof); |
| 1608 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); | 1645 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); |
| 1609 cert != credential.certs.end(); | 1646 cert != credential.certs.end(); |
| 1610 ++cert) { | 1647 ++cert) { |
| 1611 credential_ir.AddCertificate(*cert); | 1648 credential_ir.AddCertificate(*cert); |
| 1612 } | 1649 } |
| 1613 return reinterpret_cast<SpdyCredentialControlFrame*>( | 1650 return reinterpret_cast<SpdyCredentialControlFrame*>( |
| 1614 SerializeCredential(credential_ir)); | 1651 SerializeCredential(credential_ir)); |
| 1615 } | 1652 } |
| 1616 | 1653 |
| 1617 SpdySerializedFrame* SpdyFramer::SerializeCredential( | 1654 SpdySerializedFrame* SpdyFramer::SerializeCredential( |
| 1618 const SpdyCredentialIR& credential) const { | 1655 const SpdyCredentialIR& credential) const { |
| 1619 size_t size = 8; // Room for frame header. | 1656 size_t size = GetCredentialMinimumSize(); |
| 1620 size += 2; // Room for slot. | |
| 1621 size += 4 + credential.proof().length(); // Room for proof. | 1657 size += 4 + credential.proof().length(); // Room for proof. |
| 1622 for (SpdyCredentialIR::CertificateList::const_iterator it = | 1658 for (SpdyCredentialIR::CertificateList::const_iterator it = |
| 1623 credential.certificates()->begin(); | 1659 credential.certificates()->begin(); |
| 1624 it != credential.certificates()->end(); | 1660 it != credential.certificates()->end(); |
| 1625 ++it) { | 1661 ++it) { |
| 1626 size += 4 + it->length(); // Room for certificate. | 1662 size += 4 + it->length(); // Room for certificate. |
| 1627 } | 1663 } |
| 1628 | 1664 |
| 1629 SpdyFrameBuilder builder(CREDENTIAL, 0, protocol_version(), size); | 1665 SpdyFrameBuilder builder(CREDENTIAL, 0, protocol_version(), size); |
| 1630 builder.WriteUInt16(credential.slot()); | 1666 builder.WriteUInt16(credential.slot()); |
| 1667 DCHECK_EQ(GetCredentialMinimumSize(), builder.length()); |
| 1631 builder.WriteStringPiece32(credential.proof()); | 1668 builder.WriteStringPiece32(credential.proof()); |
| 1632 for (SpdyCredentialIR::CertificateList::const_iterator it = | 1669 for (SpdyCredentialIR::CertificateList::const_iterator it = |
| 1633 credential.certificates()->begin(); | 1670 credential.certificates()->begin(); |
| 1634 it != credential.certificates()->end(); | 1671 it != credential.certificates()->end(); |
| 1635 ++it) { | 1672 ++it) { |
| 1636 builder.WriteStringPiece32(*it); | 1673 builder.WriteStringPiece32(*it); |
| 1637 } | 1674 } |
| 1638 DCHECK_EQ(size, builder.length()); | 1675 DCHECK_EQ(size, builder.length()); |
| 1639 return builder.take(); | 1676 return builder.take(); |
| 1640 } | 1677 } |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1979 reinterpret_cast<const SpdyControlFrame&>(frame); | 2016 reinterpret_cast<const SpdyControlFrame&>(frame); |
| 1980 return control_frame.type() == SYN_STREAM || | 2017 return control_frame.type() == SYN_STREAM || |
| 1981 control_frame.type() == SYN_REPLY || | 2018 control_frame.type() == SYN_REPLY || |
| 1982 control_frame.type() == HEADERS; | 2019 control_frame.type() == HEADERS; |
| 1983 } | 2020 } |
| 1984 | 2021 |
| 1985 // We don't compress Data frames. | 2022 // We don't compress Data frames. |
| 1986 return false; | 2023 return false; |
| 1987 } | 2024 } |
| 1988 | 2025 |
| 1989 size_t SpdyFramer::GetMinimumControlFrameSize(int version, | |
| 1990 SpdyControlType type) { | |
| 1991 switch (type) { | |
| 1992 case SYN_STREAM: | |
| 1993 return SpdySynStreamControlFrame::size(); | |
| 1994 case SYN_REPLY: | |
| 1995 return SpdySynReplyControlFrame::size(); | |
| 1996 case RST_STREAM: | |
| 1997 return SpdyRstStreamControlFrame::size(); | |
| 1998 case SETTINGS: | |
| 1999 return SpdySettingsControlFrame::size(); | |
| 2000 case NOOP: | |
| 2001 // Even though NOOP is no longer supported, we still correctly report its | |
| 2002 // size so that it can be handled correctly as incoming data if | |
| 2003 // implementations so desire. | |
| 2004 return SpdyFrame::kHeaderSize; | |
| 2005 case PING: | |
| 2006 return SpdyPingControlFrame::size(); | |
| 2007 case GOAWAY: | |
| 2008 if (version < 3) { | |
| 2009 // SPDY 2 GOAWAY is smaller by 32 bits. Since | |
| 2010 // SpdyGoAwayControlFrame::size() returns the size for SPDY 3, we adjust | |
| 2011 // before returning here. | |
| 2012 return SpdyGoAwayControlFrame::size() - 4; | |
| 2013 } else { | |
| 2014 return SpdyGoAwayControlFrame::size(); | |
| 2015 } | |
| 2016 case HEADERS: | |
| 2017 return SpdyHeadersControlFrame::size(); | |
| 2018 case WINDOW_UPDATE: | |
| 2019 return SpdyWindowUpdateControlFrame::size(); | |
| 2020 case CREDENTIAL: | |
| 2021 return SpdyCredentialControlFrame::size(); | |
| 2022 case NUM_CONTROL_FRAME_TYPES: | |
| 2023 break; | |
| 2024 } | |
| 2025 LOG(ERROR) << "Unknown control frame type " << type; | |
| 2026 return std::numeric_limits<size_t>::max(); | |
| 2027 } | |
| 2028 | |
| 2029 /* static */ | 2026 /* static */ |
| 2030 SpdyStreamId SpdyFramer::GetControlFrameStreamId( | 2027 SpdyStreamId SpdyFramer::GetControlFrameStreamId( |
| 2031 const SpdyControlFrame* control_frame) { | 2028 const SpdyControlFrame* control_frame) { |
| 2032 SpdyStreamId stream_id = kInvalidStream; | 2029 SpdyStreamId stream_id = kInvalidStream; |
| 2033 if (control_frame != NULL) { | 2030 if (control_frame != NULL) { |
| 2034 switch (control_frame->type()) { | 2031 switch (control_frame->type()) { |
| 2035 case SYN_STREAM: | 2032 case SYN_STREAM: |
| 2036 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( | 2033 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( |
| 2037 control_frame)->stream_id(); | 2034 control_frame)->stream_id(); |
| 2038 break; | 2035 break; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2088 builder->WriteString(it->first); | 2085 builder->WriteString(it->first); |
| 2089 builder->WriteString(it->second); | 2086 builder->WriteString(it->second); |
| 2090 } else { | 2087 } else { |
| 2091 builder->WriteStringPiece32(it->first); | 2088 builder->WriteStringPiece32(it->first); |
| 2092 builder->WriteStringPiece32(it->second); | 2089 builder->WriteStringPiece32(it->second); |
| 2093 } | 2090 } |
| 2094 } | 2091 } |
| 2095 } | 2092 } |
| 2096 | 2093 |
| 2097 } // namespace net | 2094 } // namespace net |
| OLD | NEW |