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

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

Issue 17004007: [SPDY] Fix SpdySession's handling of SYN_REPLY frames (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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
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 #include "net/spdy/spdy_session.h" 5 #include "net/spdy/spdy_session.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 void SpdyStreamRequest::Reset() { 304 void SpdyStreamRequest::Reset() {
305 type_ = SPDY_BIDIRECTIONAL_STREAM; 305 type_ = SPDY_BIDIRECTIONAL_STREAM;
306 session_ = NULL; 306 session_ = NULL;
307 stream_.reset(); 307 stream_.reset();
308 url_ = GURL(); 308 url_ = GURL();
309 priority_ = MINIMUM_PRIORITY; 309 priority_ = MINIMUM_PRIORITY;
310 net_log_ = BoundNetLog(); 310 net_log_ = BoundNetLog();
311 callback_.Reset(); 311 callback_.Reset();
312 } 312 }
313 313
314 SpdySession::ActiveStreamInfo::ActiveStreamInfo()
315 : stream(NULL),
316 waiting_for_syn_reply(false) {}
317
318 SpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream)
319 : stream(stream),
320 waiting_for_syn_reply(stream->type() != SPDY_PUSH_STREAM) {}
321
322 SpdySession::ActiveStreamInfo::~ActiveStreamInfo() {}
323
324 SpdySession::PushedStreamInfo::PushedStreamInfo() : stream_id(0) {}
325
326 SpdySession::PushedStreamInfo::PushedStreamInfo(
327 SpdyStreamId stream_id,
328 base::TimeTicks creation_time)
329 : stream_id(stream_id),
330 creation_time(creation_time) {}
331
332 SpdySession::PushedStreamInfo::~PushedStreamInfo() {}
333
314 SpdySession::SpdySession(const SpdySessionKey& spdy_session_key, 334 SpdySession::SpdySession(const SpdySessionKey& spdy_session_key,
315 SpdySessionPool* spdy_session_pool, 335 SpdySessionPool* spdy_session_pool,
316 HttpServerProperties* http_server_properties, 336 HttpServerProperties* http_server_properties,
317 bool verify_domain_authentication, 337 bool verify_domain_authentication,
318 bool enable_sending_initial_settings, 338 bool enable_sending_initial_settings,
319 bool enable_credential_frames, 339 bool enable_credential_frames,
320 bool enable_compression, 340 bool enable_compression,
321 bool enable_ping_based_connection_checking, 341 bool enable_ping_based_connection_checking,
322 NextProto default_protocol, 342 NextProto default_protocol,
323 size_t stream_initial_recv_window_size, 343 size_t stream_initial_recv_window_size,
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 } 718 }
699 719
700 scoped_ptr<SpdyFrame> SpdySession::CreateSynStream( 720 scoped_ptr<SpdyFrame> SpdySession::CreateSynStream(
701 SpdyStreamId stream_id, 721 SpdyStreamId stream_id,
702 RequestPriority priority, 722 RequestPriority priority,
703 uint8 credential_slot, 723 uint8 credential_slot,
704 SpdyControlFlags flags, 724 SpdyControlFlags flags,
705 const SpdyHeaderBlock& headers) { 725 const SpdyHeaderBlock& headers) {
706 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 726 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
707 CHECK(it != active_streams_.end()); 727 CHECK(it != active_streams_.end());
708 CHECK_EQ(it->second->stream_id(), stream_id); 728 CHECK_EQ(it->second.stream->stream_id(), stream_id);
709 729
710 SendPrefacePingIfNoneInFlight(); 730 SendPrefacePingIfNoneInFlight();
711 731
712 DCHECK(buffered_spdy_framer_.get()); 732 DCHECK(buffered_spdy_framer_.get());
713 scoped_ptr<SpdyFrame> syn_frame( 733 scoped_ptr<SpdyFrame> syn_frame(
714 buffered_spdy_framer_->CreateSynStream( 734 buffered_spdy_framer_->CreateSynStream(
715 stream_id, 0, 735 stream_id, 0,
716 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), 736 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()),
717 credential_slot, flags, enable_compression_, &headers)); 737 credential_slot, flags, enable_compression_, &headers));
718 738
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 } 785 }
766 return OK; 786 return OK;
767 } 787 }
768 788
769 scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id, 789 scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id,
770 IOBuffer* data, 790 IOBuffer* data,
771 int len, 791 int len,
772 SpdyDataFlags flags) { 792 SpdyDataFlags flags) {
773 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 793 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
774 CHECK(it != active_streams_.end()); 794 CHECK(it != active_streams_.end());
775 SpdyStream* stream = it->second; 795 SpdyStream* stream = it->second.stream;
776 CHECK_EQ(stream->stream_id(), stream_id); 796 CHECK_EQ(stream->stream_id(), stream_id);
777 797
778 if (len < 0) { 798 if (len < 0) {
779 NOTREACHED(); 799 NOTREACHED();
780 return scoped_ptr<SpdyBuffer>(); 800 return scoped_ptr<SpdyBuffer>();
781 } 801 }
782 802
783 int effective_len = std::min(len, kMaxSpdyFrameChunkSize); 803 int effective_len = std::min(len, kMaxSpdyFrameChunkSize);
784 804
785 bool send_stalled_by_stream = 805 bool send_stalled_by_stream =
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 913
894 // TODO(mbelshe): We should send a RST_STREAM control frame here 914 // TODO(mbelshe): We should send a RST_STREAM control frame here
895 // so that the server can cancel a large send. 915 // so that the server can cancel a large send.
896 916
897 // For push streams, if they are being deleted normally, we leave 917 // For push streams, if they are being deleted normally, we leave
898 // the stream in the unclaimed_pushed_streams_ list. However, if 918 // the stream in the unclaimed_pushed_streams_ list. However, if
899 // the stream is errored out, clean it up entirely. 919 // the stream is errored out, clean it up entirely.
900 if (status != OK) { 920 if (status != OK) {
901 for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin(); 921 for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin();
902 it != unclaimed_pushed_streams_.end(); ++it) { 922 it != unclaimed_pushed_streams_.end(); ++it) {
903 if (stream_id == it->second.first->stream_id()) { 923 if (stream_id == it->second.stream_id) {
904 unclaimed_pushed_streams_.erase(it); 924 unclaimed_pushed_streams_.erase(it);
905 break; 925 break;
906 } 926 }
907 } 927 }
908 } 928 }
909 929
910 // The stream might have been deleted. 930 // The stream might have been deleted.
911 ActiveStreamMap::iterator it = active_streams_.find(stream_id); 931 ActiveStreamMap::iterator it = active_streams_.find(stream_id);
912 if (it == active_streams_.end()) 932 if (it == active_streams_.end())
913 return; 933 return;
914 934
915 scoped_ptr<SpdyStream> owned_stream(it->second); 935 scoped_ptr<SpdyStream> owned_stream(it->second.stream);
916 active_streams_.erase(it); 936 active_streams_.erase(it);
917 937
918 DeleteStream(owned_stream.Pass(), status); 938 DeleteStream(owned_stream.Pass(), status);
919 } 939 }
920 940
921 void SpdySession::CloseCreatedStream( 941 void SpdySession::CloseCreatedStream(
922 const base::WeakPtr<SpdyStream>& stream, int status) { 942 const base::WeakPtr<SpdyStream>& stream, int status) {
923 DCHECK_EQ(0u, stream->stream_id()); 943 DCHECK_EQ(0u, stream->stream_id());
924 944
925 scoped_ptr<SpdyStream> owned_stream(stream.get()); 945 scoped_ptr<SpdyStream> owned_stream(stream.get());
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 // The loops below are carefully written to avoid problems with 1253 // The loops below are carefully written to avoid problems with
1234 // streams closing other streams. 1254 // streams closing other streams.
1235 1255
1236 while (true) { 1256 while (true) {
1237 ActiveStreamMap::iterator it = 1257 ActiveStreamMap::iterator it =
1238 active_streams_.lower_bound(last_good_stream_id + 1); 1258 active_streams_.lower_bound(last_good_stream_id + 1);
1239 if (it == active_streams_.end()) 1259 if (it == active_streams_.end())
1240 break; 1260 break;
1241 SpdyStreamId stream_id = it->first; 1261 SpdyStreamId stream_id = it->first;
1242 streams_abandoned_count_++; 1262 streams_abandoned_count_++;
1243 LogAbandonedStream(it->second, status); 1263 LogAbandonedStream(it->second.stream, status);
1244 CloseActiveStream(stream_id, status); 1264 CloseActiveStream(stream_id, status);
1245 } 1265 }
1246 1266
1247 while (!created_streams_.empty()) { 1267 while (!created_streams_.empty()) {
1248 CreatedStreamSet::iterator it = created_streams_.begin(); 1268 CreatedStreamSet::iterator it = created_streams_.begin();
1249 LogAbandonedStream(*it, status); 1269 LogAbandonedStream(*it, status);
1250 CloseCreatedStream((*it)->GetWeakPtr(), status); 1270 CloseCreatedStream((*it)->GetWeakPtr(), status);
1251 } 1271 }
1252 1272
1253 write_queue_.RemovePendingWritesForStreamsAfter(last_good_stream_id); 1273 write_queue_.RemovePendingWritesForStreamsAfter(last_good_stream_id);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1429 stream->set_stream_id(GetNewStreamId()); 1449 stream->set_stream_id(GetNewStreamId());
1430 scoped_ptr<SpdyStream> owned_stream(stream); 1450 scoped_ptr<SpdyStream> owned_stream(stream);
1431 created_streams_.erase(stream); 1451 created_streams_.erase(stream);
1432 return owned_stream.Pass(); 1452 return owned_stream.Pass();
1433 } 1453 }
1434 1454
1435 void SpdySession::InsertActivatedStream(scoped_ptr<SpdyStream> stream) { 1455 void SpdySession::InsertActivatedStream(scoped_ptr<SpdyStream> stream) {
1436 SpdyStreamId stream_id = stream->stream_id(); 1456 SpdyStreamId stream_id = stream->stream_id();
1437 DCHECK_NE(stream_id, 0u); 1457 DCHECK_NE(stream_id, 0u);
1438 std::pair<ActiveStreamMap::iterator, bool> result = 1458 std::pair<ActiveStreamMap::iterator, bool> result =
1439 active_streams_.insert(std::make_pair(stream_id, stream.get())); 1459 active_streams_.insert(
1460 std::make_pair(stream_id, ActiveStreamInfo(stream.get())));
1440 if (result.second) { 1461 if (result.second) {
1441 ignore_result(stream.release()); 1462 ignore_result(stream.release());
1442 } else { 1463 } else {
1443 NOTREACHED(); 1464 NOTREACHED();
1444 } 1465 }
1445 } 1466 }
1446 1467
1447 void SpdySession::DeleteStream(scoped_ptr<SpdyStream> stream, int status) { 1468 void SpdySession::DeleteStream(scoped_ptr<SpdyStream> stream, int status) {
1448 if (in_flight_write_stream_.get() == stream.get()) { 1469 if (in_flight_write_stream_.get() == stream.get()) {
1449 // If we're deleting the stream for the in-flight write, we still 1470 // If we're deleting the stream for the in-flight write, we still
(...skipping 18 matching lines...) Expand all
1468 spdy_session_pool_ = NULL; 1489 spdy_session_pool_ = NULL;
1469 pool->Remove(make_scoped_refptr(this)); 1490 pool->Remove(make_scoped_refptr(this));
1470 } 1491 }
1471 } 1492 }
1472 1493
1473 base::WeakPtr<SpdyStream> SpdySession::GetActivePushStream( 1494 base::WeakPtr<SpdyStream> SpdySession::GetActivePushStream(
1474 const std::string& path) { 1495 const std::string& path) {
1475 base::StatsCounter used_push_streams("spdy.claimed_push_streams"); 1496 base::StatsCounter used_push_streams("spdy.claimed_push_streams");
1476 1497
1477 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(path); 1498 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(path);
1478 if (it != unclaimed_pushed_streams_.end()) { 1499 if (it == unclaimed_pushed_streams_.end())
1479 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM); 1500 return base::WeakPtr<SpdyStream>();
1480 base::WeakPtr<SpdyStream> stream = it->second.first->GetWeakPtr(); 1501
1481 unclaimed_pushed_streams_.erase(it); 1502 SpdyStreamId stream_id = it->second.stream_id;
1482 used_push_streams.Increment(); 1503 unclaimed_pushed_streams_.erase(it);
1483 return stream; 1504
1505 ActiveStreamMap::iterator it2 = active_streams_.find(stream_id);
1506 if (it2 == active_streams_.end()) {
1507 NOTREACHED();
1508 return base::WeakPtr<SpdyStream>();
1484 } 1509 }
1485 return base::WeakPtr<SpdyStream>(); 1510
1511 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM);
1512 used_push_streams.Increment();
1513 return it2->second.stream->GetWeakPtr();
1486 } 1514 }
1487 1515
1488 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, 1516 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info,
1489 bool* was_npn_negotiated, 1517 bool* was_npn_negotiated,
1490 NextProto* protocol_negotiated) { 1518 NextProto* protocol_negotiated) {
1491 *was_npn_negotiated = connection_->socket()->WasNpnNegotiated(); 1519 *was_npn_negotiated = connection_->socket()->WasNpnNegotiated();
1492 *protocol_negotiated = connection_->socket()->GetNegotiatedProtocol(); 1520 *protocol_negotiated = connection_->socket()->GetNegotiatedProtocol();
1493 return connection_->socket()->GetSSLInfo(ssl_info); 1521 return connection_->socket()->GetSSLInfo(ssl_info);
1494 } 1522 }
1495 1523
(...skipping 18 matching lines...) Expand all
1514 "SPDY_ERROR error_code: %d.", error_code); 1542 "SPDY_ERROR error_code: %d.", error_code);
1515 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, true, description); 1543 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, true, description);
1516 } 1544 }
1517 1545
1518 void SpdySession::OnStreamError(SpdyStreamId stream_id, 1546 void SpdySession::OnStreamError(SpdyStreamId stream_id,
1519 const std::string& description) { 1547 const std::string& description) {
1520 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 1548 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
1521 // We still want to reset the stream even if we don't know anything 1549 // We still want to reset the stream even if we don't know anything
1522 // about it. 1550 // about it.
1523 RequestPriority priority = 1551 RequestPriority priority =
1524 (it == active_streams_.end()) ? IDLE : it->second->priority(); 1552 (it == active_streams_.end()) ? IDLE : it->second.stream->priority();
1525 ResetStream(stream_id, priority, RST_STREAM_PROTOCOL_ERROR, description); 1553 ResetStream(stream_id, priority, RST_STREAM_PROTOCOL_ERROR, description);
1526 } 1554 }
1527 1555
1528 void SpdySession::OnStreamFrameData(SpdyStreamId stream_id, 1556 void SpdySession::OnStreamFrameData(SpdyStreamId stream_id,
1529 const char* data, 1557 const char* data,
1530 size_t len, 1558 size_t len,
1531 bool fin) { 1559 bool fin) {
1532 DCHECK_LT(len, 1u << 24); 1560 DCHECK_LT(len, 1u << 24);
1533 if (net_log().IsLoggingAllEvents()) { 1561 if (net_log().IsLoggingAllEvents()) {
1534 net_log().AddEvent( 1562 net_log().AddEvent(
1535 NetLog::TYPE_SPDY_SESSION_RECV_DATA, 1563 NetLog::TYPE_SPDY_SESSION_RECV_DATA,
1536 base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin)); 1564 base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin));
1537 } 1565 }
1538 1566
1539 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 1567 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
1540 1568
1541 // By the time data comes in, the stream may already be inactive. 1569 // By the time data comes in, the stream may already be inactive.
1542 if (it == active_streams_.end()) 1570 if (it == active_streams_.end())
1543 return; 1571 return;
1544 1572
1573 SpdyStream* stream = it->second.stream;
1574 CHECK_EQ(stream->stream_id(), stream_id);
1575
1576 if (it->second.waiting_for_syn_reply) {
1577 const std::string& error = "Data received before SYN_REPLY.";
1578 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
1579 ResetStream(stream_id, stream->priority(),
1580 RST_STREAM_PROTOCOL_ERROR, error);
1581 return;
1582 }
1583
1545 scoped_ptr<SpdyBuffer> buffer; 1584 scoped_ptr<SpdyBuffer> buffer;
1546 if (data) { 1585 if (data) {
1547 DCHECK_GT(len, 0u); 1586 DCHECK_GT(len, 0u);
1548 buffer.reset(new SpdyBuffer(data, len)); 1587 buffer.reset(new SpdyBuffer(data, len));
1549 1588
1550 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 1589 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) {
1551 DecreaseRecvWindowSize(static_cast<int32>(len)); 1590 DecreaseRecvWindowSize(static_cast<int32>(len));
1552 buffer->AddConsumeCallback( 1591 buffer->AddConsumeCallback(
1553 base::Bind(&SpdySession::OnReadBufferConsumed, 1592 base::Bind(&SpdySession::OnReadBufferConsumed,
1554 weak_factory_.GetWeakPtr())); 1593 weak_factory_.GetWeakPtr()));
1555 } 1594 }
1556 } else { 1595 } else {
1557 DCHECK_EQ(len, 0u); 1596 DCHECK_EQ(len, 0u);
1558 } 1597 }
1559 it->second->OnDataReceived(buffer.Pass()); 1598 stream->OnDataReceived(buffer.Pass());
1560 } 1599 }
1561 1600
1562 void SpdySession::OnSettings(bool clear_persisted) { 1601 void SpdySession::OnSettings(bool clear_persisted) {
1563 if (clear_persisted) 1602 if (clear_persisted)
1564 http_server_properties_->ClearSpdySettings(host_port_pair()); 1603 http_server_properties_->ClearSpdySettings(host_port_pair());
1565 1604
1566 if (net_log_.IsLoggingAllEvents()) { 1605 if (net_log_.IsLoggingAllEvents()) {
1567 net_log_.AddEvent( 1606 net_log_.AddEvent(
1568 NetLog::TYPE_SPDY_SESSION_RECV_SETTINGS, 1607 NetLog::TYPE_SPDY_SESSION_RECV_SETTINGS,
1569 base::Bind(&NetLogSpdySettingsCallback, host_port_pair(), 1608 base::Bind(&NetLogSpdySettingsCallback, host_port_pair(),
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1679 // is trusted explicitly via the --trusted-spdy-proxy switch. 1718 // is trusted explicitly via the --trusted-spdy-proxy switch.
1680 if (trusted_spdy_proxy_.Equals(host_port_pair())) { 1719 if (trusted_spdy_proxy_.Equals(host_port_pair())) {
1681 // Disallow pushing of HTTPS content. 1720 // Disallow pushing of HTTPS content.
1682 if (gurl.SchemeIs("https")) { 1721 if (gurl.SchemeIs("https")) {
1683 ResetStream(stream_id, request_priority, RST_STREAM_REFUSED_STREAM, 1722 ResetStream(stream_id, request_priority, RST_STREAM_REFUSED_STREAM,
1684 base::StringPrintf( 1723 base::StringPrintf(
1685 "Rejected push of Cross Origin HTTPS content %d", 1724 "Rejected push of Cross Origin HTTPS content %d",
1686 associated_stream_id)); 1725 associated_stream_id));
1687 } 1726 }
1688 } else { 1727 } else {
1689 GURL associated_url(associated_it->second->GetUrl()); 1728 GURL associated_url(associated_it->second.stream->GetUrl());
1690 if (associated_url.GetOrigin() != gurl.GetOrigin()) { 1729 if (associated_url.GetOrigin() != gurl.GetOrigin()) {
1691 ResetStream(stream_id, request_priority, RST_STREAM_REFUSED_STREAM, 1730 ResetStream(stream_id, request_priority, RST_STREAM_REFUSED_STREAM,
1692 base::StringPrintf( 1731 base::StringPrintf(
1693 "Rejected Cross Origin Push Stream %d", 1732 "Rejected Cross Origin Push Stream %d",
1694 associated_stream_id)); 1733 associated_stream_id));
1695 return; 1734 return;
1696 } 1735 }
1697 } 1736 }
1698 1737
1699 // There should not be an existing pushed stream with the same path. 1738 // There should not be an existing pushed stream with the same path.
1700 if (unclaimed_pushed_streams_.find(url) != unclaimed_pushed_streams_.end()) { 1739 if (unclaimed_pushed_streams_.find(url) != unclaimed_pushed_streams_.end()) {
1701 ResetStream(stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR, 1740 ResetStream(stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR,
1702 "Received duplicate pushed stream with url: " + url); 1741 "Received duplicate pushed stream with url: " + url);
1703 return; 1742 return;
1704 } 1743 }
1705 1744
1706 scoped_ptr<SpdyStream> stream( 1745 scoped_ptr<SpdyStream> stream(
1707 new SpdyStream(SPDY_PUSH_STREAM, this, gurl.PathForRequest(), 1746 new SpdyStream(SPDY_PUSH_STREAM, this, gurl.PathForRequest(),
1708 request_priority, 1747 request_priority,
1709 stream_initial_send_window_size_, 1748 stream_initial_send_window_size_,
1710 stream_initial_recv_window_size_, 1749 stream_initial_recv_window_size_,
1711 net_log_)); 1750 net_log_));
1712 stream->set_stream_id(stream_id); 1751 stream->set_stream_id(stream_id);
1713 1752
1714 DeleteExpiredPushedStreams(); 1753 DeleteExpiredPushedStreams();
1715 unclaimed_pushed_streams_[url] = 1754 unclaimed_pushed_streams_[url] = PushedStreamInfo(stream_id, time_func_());
1716 std::pair<SpdyStream*, base::TimeTicks>(stream.get(), time_func_());
1717 1755
1718 stream->set_response_received(); 1756 stream->set_response_received();
1719 InsertActivatedStream(stream.Pass()); 1757 InsertActivatedStream(stream.Pass());
1720 1758
1721 ActiveStreamMap::iterator it = active_streams_.find(stream_id); 1759 ActiveStreamMap::iterator it = active_streams_.find(stream_id);
1722 if (it == active_streams_.end()) { 1760 if (it == active_streams_.end()) {
1723 NOTREACHED(); 1761 NOTREACHED();
1724 return; 1762 return;
1725 } 1763 }
1726 1764
1727 // Parse the headers. 1765 // Parse the headers.
1728 if (!Respond(headers, it->second)) 1766 if (!Respond(headers, it->second.stream))
1729 return; 1767 return;
1730 1768
1731 base::StatsCounter push_requests("spdy.pushed_streams"); 1769 base::StatsCounter push_requests("spdy.pushed_streams");
1732 push_requests.Increment(); 1770 push_requests.Increment();
1733 } 1771 }
1734 1772
1735 void SpdySession::DeleteExpiredPushedStreams() { 1773 void SpdySession::DeleteExpiredPushedStreams() {
1736 if (unclaimed_pushed_streams_.empty()) 1774 if (unclaimed_pushed_streams_.empty())
1737 return; 1775 return;
1738 1776
1739 // Check that adequate time has elapsed since the last sweep. 1777 // Check that adequate time has elapsed since the last sweep.
1740 if (time_func_() < next_unclaimed_push_stream_sweep_time_) 1778 if (time_func_() < next_unclaimed_push_stream_sweep_time_)
1741 return; 1779 return;
1742 1780
1743 // Delete old streams. 1781 // Gather old streams to delete.
1744 base::TimeTicks minimum_freshness = time_func_() - 1782 base::TimeTicks minimum_freshness = time_func_() -
1745 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); 1783 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds);
1746 PushedStreamMap::iterator it; 1784 std::vector<SpdyStreamId> streams_to_close;
1747 for (it = unclaimed_pushed_streams_.begin(); 1785 for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin();
1748 it != unclaimed_pushed_streams_.end(); ) { 1786 it != unclaimed_pushed_streams_.end(); ++it) {
1749 SpdyStream* stream = it->second.first; 1787 if (minimum_freshness > it->second.creation_time)
1750 base::TimeTicks creation_time = it->second.second; 1788 streams_to_close.push_back(it->second.stream_id);
1751 // CloseActiveStream() will invalidate the current iterator, so
1752 // move to next.
1753 ++it;
1754 if (minimum_freshness > creation_time) {
1755 base::StatsCounter abandoned_push_streams(
1756 "spdy.abandoned_push_streams");
1757 base::StatsCounter abandoned_streams("spdy.abandoned_streams");
1758 abandoned_push_streams.Increment();
1759 abandoned_streams.Increment();
1760 streams_abandoned_count_++;
1761 CloseActiveStream(stream->stream_id(), ERR_INVALID_SPDY_STREAM);
1762 }
1763 } 1789 }
1790
1791 for (std::vector<SpdyStreamId>::const_iterator it = streams_to_close.begin();
1792 it != streams_to_close.end(); ++it) {
1793 base::StatsCounter abandoned_push_streams(
1794 "spdy.abandoned_push_streams");
1795 base::StatsCounter abandoned_streams("spdy.abandoned_streams");
1796 abandoned_push_streams.Increment();
1797 abandoned_streams.Increment();
1798 streams_abandoned_count_++;
1799 // CloseActiveStream() will remove the stream from
1800 // |unclaimed_pushed_streams_|.
1801 CloseActiveStream(*it, ERR_INVALID_SPDY_STREAM);
1802 }
1803
1764 next_unclaimed_push_stream_sweep_time_ = time_func_() + 1804 next_unclaimed_push_stream_sweep_time_ = time_func_() +
1765 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); 1805 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds);
1766 } 1806 }
1767 1807
1768 void SpdySession::OnSynReply(SpdyStreamId stream_id, 1808 void SpdySession::OnSynReply(SpdyStreamId stream_id,
1769 bool fin, 1809 bool fin,
1770 const SpdyHeaderBlock& headers) { 1810 const SpdyHeaderBlock& headers) {
1771 if (net_log().IsLoggingAllEvents()) { 1811 if (net_log().IsLoggingAllEvents()) {
1772 net_log().AddEvent( 1812 net_log().AddEvent(
1773 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, 1813 NetLog::TYPE_SPDY_SESSION_SYN_REPLY,
1774 base::Bind(&NetLogSpdySynCallback, 1814 base::Bind(&NetLogSpdySynCallback,
1775 &headers, fin, false, // not unidirectional 1815 &headers, fin, false, // not unidirectional
1776 stream_id, 0)); 1816 stream_id, 0));
1777 } 1817 }
1778 1818
1779 ActiveStreamMap::iterator it = active_streams_.find(stream_id); 1819 ActiveStreamMap::iterator it = active_streams_.find(stream_id);
1780 if (it == active_streams_.end()) { 1820 if (it == active_streams_.end()) {
1781 // NOTE: it may just be that the stream was cancelled. 1821 // NOTE: it may just be that the stream was cancelled.
1782 return; 1822 return;
1783 } 1823 }
1784 1824
1785 SpdyStream* stream = it->second; 1825 SpdyStream* stream = it->second.stream;
1786 CHECK_EQ(stream->stream_id(), stream_id); 1826 CHECK_EQ(stream->stream_id(), stream_id);
1787 1827
1788 if (stream->response_received()) { 1828 if (!it->second.waiting_for_syn_reply) {
1789 stream->LogStreamError(ERR_SYN_REPLY_NOT_RECEIVED, 1829 const std::string& error =
1790 "Received duplicate SYN_REPLY for stream."); 1830 "Received duplicate SYN_REPLY for stream.";
1791 RecordProtocolErrorHistogram(PROTOCOL_ERROR_SYN_REPLY_NOT_RECEIVED); 1831 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
Ryan Hamilton 2013/06/21 15:35:37 Did this get lost or is it called by LogStreamErro
akalin 2013/06/21 18:30:44 Called by ResetStream
1792 CloseActiveStream(stream->stream_id(), ERR_SPDY_PROTOCOL_ERROR); 1832 ResetStream(stream_id, stream->priority(),
1833 RST_STREAM_STREAM_IN_USE, error);
1793 return; 1834 return;
1794 } 1835 }
1795 stream->set_response_received(); 1836 stream->set_response_received();
1837 it->second.waiting_for_syn_reply = false;
1796 1838
1797 Respond(headers, stream); 1839 Respond(headers, stream);
1798 } 1840 }
1799 1841
1800 void SpdySession::OnHeaders(SpdyStreamId stream_id, 1842 void SpdySession::OnHeaders(SpdyStreamId stream_id,
1801 bool fin, 1843 bool fin,
1802 const SpdyHeaderBlock& headers) { 1844 const SpdyHeaderBlock& headers) {
1803 if (net_log().IsLoggingAllEvents()) { 1845 if (net_log().IsLoggingAllEvents()) {
1804 net_log().AddEvent( 1846 net_log().AddEvent(
1805 NetLog::TYPE_SPDY_SESSION_RECV_HEADERS, 1847 NetLog::TYPE_SPDY_SESSION_RECV_HEADERS,
1806 base::Bind(&NetLogSpdySynCallback, 1848 base::Bind(&NetLogSpdySynCallback,
1807 &headers, fin, /*unidirectional=*/false, 1849 &headers, fin, /*unidirectional=*/false,
1808 stream_id, 0)); 1850 stream_id, 0));
1809 } 1851 }
1810 1852
1811 ActiveStreamMap::iterator it = active_streams_.find(stream_id); 1853 ActiveStreamMap::iterator it = active_streams_.find(stream_id);
1812 if (it == active_streams_.end()) { 1854 if (it == active_streams_.end()) {
1813 // NOTE: it may just be that the stream was cancelled. 1855 // NOTE: it may just be that the stream was cancelled.
1814 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; 1856 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id;
1815 return; 1857 return;
1816 } 1858 }
1817 1859
1818 CHECK_EQ(it->second->stream_id(), stream_id); 1860 SpdyStream* stream = it->second.stream;
1861 CHECK_EQ(stream->stream_id(), stream_id);
1819 1862
1820 int rv = it->second->OnHeaders(headers); 1863 int rv = stream->OnHeaders(headers);
1821 if (rv < 0) { 1864 if (rv < 0) {
1822 DCHECK_NE(rv, ERR_IO_PENDING); 1865 DCHECK_NE(rv, ERR_IO_PENDING);
1823 CloseActiveStream(stream_id, rv); 1866 CloseActiveStream(stream_id, rv);
1824 } 1867 }
1825 } 1868 }
1826 1869
1827 void SpdySession::OnRstStream(SpdyStreamId stream_id, 1870 void SpdySession::OnRstStream(SpdyStreamId stream_id,
1828 SpdyRstStreamStatus status) { 1871 SpdyRstStreamStatus status) {
1829 std::string description; 1872 std::string description;
1830 net_log().AddEvent( 1873 net_log().AddEvent(
1831 NetLog::TYPE_SPDY_SESSION_RST_STREAM, 1874 NetLog::TYPE_SPDY_SESSION_RST_STREAM,
1832 base::Bind(&NetLogSpdyRstCallback, 1875 base::Bind(&NetLogSpdyRstCallback,
1833 stream_id, status, &description)); 1876 stream_id, status, &description));
1834 1877
1835 ActiveStreamMap::iterator it = active_streams_.find(stream_id); 1878 ActiveStreamMap::iterator it = active_streams_.find(stream_id);
1836 if (it == active_streams_.end()) { 1879 if (it == active_streams_.end()) {
1837 // NOTE: it may just be that the stream was cancelled. 1880 // NOTE: it may just be that the stream was cancelled.
1838 LOG(WARNING) << "Received RST for invalid stream" << stream_id; 1881 LOG(WARNING) << "Received RST for invalid stream" << stream_id;
1839 return; 1882 return;
1840 } 1883 }
1841 1884
1842 CHECK_EQ(it->second->stream_id(), stream_id); 1885 CHECK_EQ(it->second.stream->stream_id(), stream_id);
1843 1886
1844 if (status == 0) { 1887 if (status == 0) {
1845 it->second->OnDataReceived(scoped_ptr<SpdyBuffer>()); 1888 it->second.stream->OnDataReceived(scoped_ptr<SpdyBuffer>());
1846 } else if (status == RST_STREAM_REFUSED_STREAM) { 1889 } else if (status == RST_STREAM_REFUSED_STREAM) {
1847 CloseActiveStream(stream_id, ERR_SPDY_SERVER_REFUSED_STREAM); 1890 CloseActiveStream(stream_id, ERR_SPDY_SERVER_REFUSED_STREAM);
1848 } else { 1891 } else {
1849 RecordProtocolErrorHistogram( 1892 RecordProtocolErrorHistogram(
1850 PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM); 1893 PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM);
1851 it->second->LogStreamError( 1894 it->second.stream->LogStreamError(
1852 ERR_SPDY_PROTOCOL_ERROR, 1895 ERR_SPDY_PROTOCOL_ERROR,
1853 base::StringPrintf("SPDY stream closed with status: %d", status)); 1896 base::StringPrintf("SPDY stream closed with status: %d", status));
1854 // TODO(mbelshe): Map from Spdy-protocol errors to something sensical. 1897 // TODO(mbelshe): Map from Spdy-protocol errors to something sensical.
1855 // For now, it doesn't matter much - it is a protocol error. 1898 // For now, it doesn't matter much - it is a protocol error.
1856 CloseActiveStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); 1899 CloseActiveStream(stream_id, ERR_SPDY_PROTOCOL_ERROR);
1857 } 1900 }
1858 } 1901 }
1859 1902
1860 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, 1903 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id,
1861 SpdyGoAwayStatus status) { 1904 SpdyGoAwayStatus status) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1930 if (flow_control_state_ < FLOW_CONTROL_STREAM) { 1973 if (flow_control_state_ < FLOW_CONTROL_STREAM) {
1931 // TODO(akalin): Record an error and close the session. 1974 // TODO(akalin): Record an error and close the session.
1932 LOG(WARNING) << "Received WINDOW_UPDATE for stream " << stream_id 1975 LOG(WARNING) << "Received WINDOW_UPDATE for stream " << stream_id
1933 << " when flow control is not turned on"; 1976 << " when flow control is not turned on";
1934 return; 1977 return;
1935 } 1978 }
1936 1979
1937 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 1980 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
1938 1981
1939 if (it == active_streams_.end()) { 1982 if (it == active_streams_.end()) {
1940 // TODO(akalin): Record an error and close the session. 1983 // NOTE: it may just be that the stream was cancelled.
1941 LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id; 1984 LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id;
1942 return; 1985 return;
1943 } 1986 }
1944 1987
1988 SpdyStream* stream = it->second.stream;
1989 CHECK_EQ(stream->stream_id(), stream_id);
1990
1945 if (delta_window_size < 1u) { 1991 if (delta_window_size < 1u) {
1946 ResetStream(stream_id, it->second->priority(), 1992 ResetStream(stream_id, it->second.stream->priority(),
1947 RST_STREAM_FLOW_CONTROL_ERROR, 1993 RST_STREAM_FLOW_CONTROL_ERROR,
1948 base::StringPrintf( 1994 base::StringPrintf(
1949 "Received WINDOW_UPDATE with an invalid " 1995 "Received WINDOW_UPDATE with an invalid "
1950 "delta_window_size %ud", delta_window_size)); 1996 "delta_window_size %ud", delta_window_size));
1951 return; 1997 return;
1952 } 1998 }
1953 1999
1954 CHECK_EQ(it->second->stream_id(), stream_id); 2000 CHECK_EQ(it->second.stream->stream_id(), stream_id);
1955 it->second->IncreaseSendWindowSize(static_cast<int32>(delta_window_size)); 2001 it->second.stream->IncreaseSendWindowSize(
2002 static_cast<int32>(delta_window_size));
1956 } 2003 }
1957 } 2004 }
1958 2005
1959 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, 2006 void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id,
1960 uint32 delta_window_size) { 2007 uint32 delta_window_size) {
1961 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 2008 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM);
1962 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 2009 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
1963 CHECK(it != active_streams_.end()); 2010 CHECK(it != active_streams_.end());
1964 CHECK_EQ(it->second->stream_id(), stream_id); 2011 CHECK_EQ(it->second.stream->stream_id(), stream_id);
1965 SendWindowUpdateFrame(stream_id, delta_window_size, it->second->priority()); 2012 SendWindowUpdateFrame(
2013 stream_id, delta_window_size, it->second.stream->priority());
1966 } 2014 }
1967 2015
1968 void SpdySession::SendInitialSettings() { 2016 void SpdySession::SendInitialSettings() {
1969 // First notify the server about the settings they should use when 2017 // First notify the server about the settings they should use when
1970 // communicating with us. 2018 // communicating with us.
1971 if (GetProtocolVersion() >= 2 && enable_sending_initial_settings_) { 2019 if (GetProtocolVersion() >= 2 && enable_sending_initial_settings_) {
1972 SettingsMap settings_map; 2020 SettingsMap settings_map;
1973 // Create a new settings frame notifying the sever of our 2021 // Create a new settings frame notifying the sever of our
1974 // max_concurrent_streams_ and initial window size. 2022 // max_concurrent_streams_ and initial window size.
1975 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = 2023 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] =
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 NetLog::IntegerCallback("delta_window_size", delta_window_size)); 2102 NetLog::IntegerCallback("delta_window_size", delta_window_size));
2055 break; 2103 break;
2056 } 2104 }
2057 } 2105 }
2058 } 2106 }
2059 2107
2060 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { 2108 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) {
2061 DCHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 2109 DCHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM);
2062 for (ActiveStreamMap::iterator it = active_streams_.begin(); 2110 for (ActiveStreamMap::iterator it = active_streams_.begin();
2063 it != active_streams_.end(); ++it) { 2111 it != active_streams_.end(); ++it) {
2064 it->second->AdjustSendWindowSize(delta_window_size); 2112 it->second.stream->AdjustSendWindowSize(delta_window_size);
2065 } 2113 }
2066 2114
2067 for (CreatedStreamSet::const_iterator it = created_streams_.begin(); 2115 for (CreatedStreamSet::const_iterator it = created_streams_.begin();
2068 it != created_streams_.end(); it++) { 2116 it != created_streams_.end(); it++) {
2069 (*it)->AdjustSendWindowSize(delta_window_size); 2117 (*it)->AdjustSendWindowSize(delta_window_size);
2070 } 2118 }
2071 } 2119 }
2072 2120
2073 void SpdySession::SendPrefacePingIfNoneInFlight() { 2121 void SpdySession::SendPrefacePingIfNoneInFlight() {
2074 if (pings_in_flight_ || !enable_ping_based_connection_checking_) 2122 if (pings_in_flight_ || !enable_ping_based_connection_checking_)
2075 return; 2123 return;
2076 2124
2077 base::TimeTicks now = base::TimeTicks::Now(); 2125 base::TimeTicks now = base::TimeTicks::Now();
2078 // If there is no activity in the session, then send a preface-PING. 2126 // If there is no activity in the session, then send a preface-PING.
2079 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) 2127 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_)
2080 SendPrefacePing(); 2128 SendPrefacePing();
2081 } 2129 }
2082 2130
2083 void SpdySession::SendPrefacePing() { 2131 void SpdySession::SendPrefacePing() {
2084 WritePingFrame(next_ping_id_); 2132 WritePingFrame(next_ping_id_);
2085 } 2133 }
2086 2134
2087 void SpdySession::SendWindowUpdateFrame(SpdyStreamId stream_id, 2135 void SpdySession::SendWindowUpdateFrame(SpdyStreamId stream_id,
2088 uint32 delta_window_size, 2136 uint32 delta_window_size,
2089 RequestPriority priority) { 2137 RequestPriority priority) {
2090 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 2138 CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM);
2091 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 2139 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
2092 if (it != active_streams_.end()) { 2140 if (it != active_streams_.end()) {
2093 CHECK_EQ(it->second->stream_id(), stream_id); 2141 CHECK_EQ(it->second.stream->stream_id(), stream_id);
2094 } else { 2142 } else {
2095 CHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2143 CHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION);
2096 CHECK_EQ(stream_id, kSessionFlowControlStreamId); 2144 CHECK_EQ(stream_id, kSessionFlowControlStreamId);
2097 } 2145 }
2098 2146
2099 net_log_.AddEvent( 2147 net_log_.AddEvent(
2100 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE_FRAME, 2148 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE_FRAME,
2101 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, 2149 base::Bind(&NetLogSpdyWindowUpdateFrameCallback,
2102 stream_id, delta_window_size)); 2150 stream_id, delta_window_size));
2103 2151
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
2437 old_size = GetTotalSize(stream_send_unstall_queue_); 2485 old_size = GetTotalSize(stream_send_unstall_queue_);
2438 2486
2439 SpdyStreamId stream_id = PopStreamToPossiblyResume(); 2487 SpdyStreamId stream_id = PopStreamToPossiblyResume();
2440 if (stream_id == 0) 2488 if (stream_id == 0)
2441 break; 2489 break;
2442 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 2490 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
2443 // The stream may actually still be send-stalled after this (due 2491 // The stream may actually still be send-stalled after this (due
2444 // to its own send window) but that's okay -- it'll then be 2492 // to its own send window) but that's okay -- it'll then be
2445 // resumed once its send window increases. 2493 // resumed once its send window increases.
2446 if (it != active_streams_.end()) 2494 if (it != active_streams_.end())
2447 it->second->PossiblyResumeIfSendStalled(); 2495 it->second.stream->PossiblyResumeIfSendStalled();
2448 2496
2449 // The size should decrease unless we got send-stalled again. 2497 // The size should decrease unless we got send-stalled again.
2450 if (!IsSendStalled()) 2498 if (!IsSendStalled())
2451 DCHECK_LT(GetTotalSize(stream_send_unstall_queue_), old_size); 2499 DCHECK_LT(GetTotalSize(stream_send_unstall_queue_), old_size);
2452 } 2500 }
2453 } 2501 }
2454 2502
2455 SpdyStreamId SpdySession::PopStreamToPossiblyResume() { 2503 SpdyStreamId SpdySession::PopStreamToPossiblyResume() {
2456 for (int i = NUM_PRIORITIES - 1; i >= 0; --i) { 2504 for (int i = NUM_PRIORITIES - 1; i >= 0; --i) {
2457 std::deque<SpdyStreamId>* queue = &stream_send_unstall_queue_[i]; 2505 std::deque<SpdyStreamId>* queue = &stream_send_unstall_queue_[i];
2458 if (!queue->empty()) { 2506 if (!queue->empty()) {
2459 SpdyStreamId stream_id = queue->front(); 2507 SpdyStreamId stream_id = queue->front();
2460 queue->pop_front(); 2508 queue->pop_front();
2461 return stream_id; 2509 return stream_id;
2462 } 2510 }
2463 } 2511 }
2464 return 0; 2512 return 0;
2465 } 2513 }
2466 2514
2467 } // namespace net 2515 } // namespace net
OLDNEW
« net/spdy/spdy_session.h ('K') | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698