Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/auto_reset.h" | |
| 7 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 9 #include "base/logging.h" |
| 9 #include "base/memory/linked_ptr.h" | 10 #include "base/memory/linked_ptr.h" |
| 10 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 11 #include "base/metrics/field_trial.h" | 12 #include "base/metrics/field_trial.h" |
| 12 #include "base/metrics/stats_counters.h" | 13 #include "base/metrics/stats_counters.h" |
| 13 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 14 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
| 15 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 16 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 } | 166 } |
| 166 | 167 |
| 167 private: | 168 private: |
| 168 ~NetLogSpdyRstParameter() {} | 169 ~NetLogSpdyRstParameter() {} |
| 169 const spdy::SpdyStreamId stream_id_; | 170 const spdy::SpdyStreamId stream_id_; |
| 170 const int status_; | 171 const int status_; |
| 171 | 172 |
| 172 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyRstParameter); | 173 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyRstParameter); |
| 173 }; | 174 }; |
| 174 | 175 |
| 176 class NetLogSpdyPingParameter : public NetLog::EventParameters { | |
| 177 public: | |
| 178 explicit NetLogSpdyPingParameter(uint32 unique_id) : unique_id_(unique_id) {} | |
| 179 | |
| 180 virtual Value* ToValue() const { | |
| 181 DictionaryValue* dict = new DictionaryValue(); | |
| 182 dict->SetInteger("unique_id", unique_id_); | |
| 183 return dict; | |
| 184 } | |
| 185 | |
| 186 private: | |
| 187 ~NetLogSpdyPingParameter() {} | |
| 188 const uint32 unique_id_; | |
| 189 | |
| 190 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyPingParameter); | |
| 191 }; | |
| 192 | |
| 175 class NetLogSpdyGoAwayParameter : public NetLog::EventParameters { | 193 class NetLogSpdyGoAwayParameter : public NetLog::EventParameters { |
| 176 public: | 194 public: |
| 177 NetLogSpdyGoAwayParameter(spdy::SpdyStreamId last_stream_id, | 195 NetLogSpdyGoAwayParameter(spdy::SpdyStreamId last_stream_id, |
| 178 int active_streams, | 196 int active_streams, |
| 179 int unclaimed_streams) | 197 int unclaimed_streams) |
| 180 : last_stream_id_(last_stream_id), | 198 : last_stream_id_(last_stream_id), |
| 181 active_streams_(active_streams), | 199 active_streams_(active_streams), |
| 182 unclaimed_streams_(unclaimed_streams) {} | 200 unclaimed_streams_(unclaimed_streams) {} |
| 183 | 201 |
| 184 virtual Value* ToValue() const { | 202 virtual Value* ToValue() const { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 max_concurrent_streams_(init_max_concurrent_streams_), | 257 max_concurrent_streams_(init_max_concurrent_streams_), |
| 240 streams_initiated_count_(0), | 258 streams_initiated_count_(0), |
| 241 streams_pushed_count_(0), | 259 streams_pushed_count_(0), |
| 242 streams_pushed_and_claimed_count_(0), | 260 streams_pushed_and_claimed_count_(0), |
| 243 streams_abandoned_count_(0), | 261 streams_abandoned_count_(0), |
| 244 frames_received_(0), | 262 frames_received_(0), |
| 245 bytes_received_(0), | 263 bytes_received_(0), |
| 246 sent_settings_(false), | 264 sent_settings_(false), |
| 247 received_settings_(false), | 265 received_settings_(false), |
| 248 stalled_streams_(0), | 266 stalled_streams_(0), |
| 267 pings_in_flight_(0), | |
| 268 unique_id_counter_(1), | |
| 269 follower_ping_pending_(false), | |
| 249 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize), | 270 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize), |
| 250 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize), | 271 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize), |
| 251 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), | 272 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), |
| 252 verify_domain_authentication_(verify_domain_authentication) { | 273 verify_domain_authentication_(verify_domain_authentication) { |
| 253 DCHECK(HttpStreamFactory::spdy_enabled()); | 274 DCHECK(HttpStreamFactory::spdy_enabled()); |
| 254 net_log_.BeginEvent( | 275 net_log_.BeginEvent( |
| 255 NetLog::TYPE_SPDY_SESSION, | 276 NetLog::TYPE_SPDY_SESSION, |
| 256 make_scoped_refptr( | 277 make_scoped_refptr( |
| 257 new NetLogSpdySessionParameter(host_port_proxy_pair_))); | 278 new NetLogSpdySessionParameter(host_port_proxy_pair_))); |
| 258 | 279 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 467 spdy::SpdyStreamId stream_id, | 488 spdy::SpdyStreamId stream_id, |
| 468 RequestPriority priority, | 489 RequestPriority priority, |
| 469 spdy::SpdyControlFlags flags, | 490 spdy::SpdyControlFlags flags, |
| 470 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { | 491 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { |
| 471 // Find our stream | 492 // Find our stream |
| 472 if (!IsStreamActive(stream_id)) | 493 if (!IsStreamActive(stream_id)) |
| 473 return ERR_INVALID_SPDY_STREAM; | 494 return ERR_INVALID_SPDY_STREAM; |
| 474 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; | 495 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; |
| 475 CHECK_EQ(stream->stream_id(), stream_id); | 496 CHECK_EQ(stream->stream_id(), stream_id); |
| 476 | 497 |
| 498 int result = SendPing(stream_id); | |
| 499 if (result != ERR_IO_PENDING) | |
| 500 return result; | |
| 501 | |
| 477 scoped_ptr<spdy::SpdySynStreamControlFrame> syn_frame( | 502 scoped_ptr<spdy::SpdySynStreamControlFrame> syn_frame( |
| 478 spdy_framer_.CreateSynStream( | 503 spdy_framer_.CreateSynStream( |
| 479 stream_id, 0, | 504 stream_id, 0, |
| 480 ConvertRequestPriorityToSpdyPriority(priority), | 505 ConvertRequestPriorityToSpdyPriority(priority), |
| 481 flags, false, headers.get())); | 506 flags, false, headers.get())); |
| 482 QueueFrame(syn_frame.get(), priority, stream); | 507 QueueFrame(syn_frame.get(), priority, stream); |
| 483 | 508 |
| 484 base::StatsCounter spdy_requests("spdy.requests"); | 509 base::StatsCounter spdy_requests("spdy.requests"); |
| 485 spdy_requests.Increment(); | 510 spdy_requests.Increment(); |
| 486 streams_initiated_count_++; | 511 streams_initiated_count_++; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 605 // Session is tearing down. | 630 // Session is tearing down. |
| 606 net::Error error = static_cast<net::Error>(bytes_read); | 631 net::Error error = static_cast<net::Error>(bytes_read); |
| 607 if (bytes_read == 0) | 632 if (bytes_read == 0) |
| 608 error = ERR_CONNECTION_CLOSED; | 633 error = ERR_CONNECTION_CLOSED; |
| 609 CloseSessionOnError(error, true); | 634 CloseSessionOnError(error, true); |
| 610 return; | 635 return; |
| 611 } | 636 } |
| 612 | 637 |
| 613 bytes_received_ += bytes_read; | 638 bytes_received_ += bytes_read; |
| 614 | 639 |
| 640 received_data_time_ = base::TimeTicks::Now(); | |
| 641 | |
| 615 // The SpdyFramer will use callbacks onto |this| as it parses frames. | 642 // The SpdyFramer will use callbacks onto |this| as it parses frames. |
| 616 // When errors occur, those callbacks can lead to teardown of all references | 643 // When errors occur, those callbacks can lead to teardown of all references |
| 617 // to |this|, so maintain a reference to self during this call for safe | 644 // to |this|, so maintain a reference to self during this call for safe |
| 618 // cleanup. | 645 // cleanup. |
| 619 scoped_refptr<SpdySession> self(this); | 646 scoped_refptr<SpdySession> self(this); |
| 620 | 647 |
| 621 char *data = read_buffer_->data(); | 648 char *data = read_buffer_->data(); |
| 622 while (bytes_read && | 649 while (bytes_read && |
| 623 spdy_framer_.error_code() == spdy::SpdyFramer::SPDY_NO_ERROR) { | 650 spdy_framer_.error_code() == spdy::SpdyFramer::SPDY_NO_ERROR) { |
| 624 uint32 bytes_processed = spdy_framer_.ProcessInput(data, bytes_read); | 651 uint32 bytes_processed = spdy_framer_.ProcessInput(data, bytes_read); |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1222 return; | 1249 return; |
| 1223 } | 1250 } |
| 1224 } | 1251 } |
| 1225 | 1252 |
| 1226 frames_received_++; | 1253 frames_received_++; |
| 1227 | 1254 |
| 1228 switch (type) { | 1255 switch (type) { |
| 1229 case spdy::GOAWAY: | 1256 case spdy::GOAWAY: |
| 1230 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame)); | 1257 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame)); |
| 1231 break; | 1258 break; |
| 1259 case spdy::PING: | |
| 1260 OnPing(*reinterpret_cast<const spdy::SpdyPingControlFrame*>(frame)); | |
| 1261 break; | |
| 1232 case spdy::SETTINGS: | 1262 case spdy::SETTINGS: |
| 1233 OnSettings( | 1263 OnSettings( |
| 1234 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); | 1264 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); |
| 1235 break; | 1265 break; |
| 1236 case spdy::RST_STREAM: | 1266 case spdy::RST_STREAM: |
| 1237 OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); | 1267 OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); |
| 1238 break; | 1268 break; |
| 1239 case spdy::SYN_STREAM: | 1269 case spdy::SYN_STREAM: |
| 1240 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), | 1270 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), |
| 1241 headers); | 1271 headers); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1310 CloseAllStreams(net::ERR_ABORTED); | 1340 CloseAllStreams(net::ERR_ABORTED); |
| 1311 | 1341 |
| 1312 // TODO(willchan): Cancel any streams that are past the GoAway frame's | 1342 // TODO(willchan): Cancel any streams that are past the GoAway frame's |
| 1313 // |last_accepted_stream_id|. | 1343 // |last_accepted_stream_id|. |
| 1314 | 1344 |
| 1315 // Don't bother killing any streams that are still reading. They'll either | 1345 // Don't bother killing any streams that are still reading. They'll either |
| 1316 // complete successfully or get an ERR_CONNECTION_CLOSED when the socket is | 1346 // complete successfully or get an ERR_CONNECTION_CLOSED when the socket is |
| 1317 // closed. | 1347 // closed. |
| 1318 } | 1348 } |
| 1319 | 1349 |
| 1350 void SpdySession::OnPing(const spdy::SpdyPingControlFrame& frame) { | |
| 1351 --pings_in_flight_; | |
|
willchan no longer on Chromium
2011/10/13 15:47:17
If you aren't doing any PING validation of the uni
ramant (doing other things)
2011/10/13 21:41:14
Decrements pings_in_flight_ only if client had sen
| |
| 1352 net_log_.AddEvent( | |
| 1353 NetLog::TYPE_SPDY_SESSION_PING, | |
| 1354 make_scoped_refptr(new NetLogSpdyPingParameter(frame.unique_id()))); | |
| 1355 } | |
| 1356 | |
| 1320 void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) { | 1357 void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) { |
| 1321 spdy::SpdySettings settings; | 1358 spdy::SpdySettings settings; |
| 1322 if (spdy_framer_.ParseSettings(&frame, &settings)) { | 1359 if (spdy_framer_.ParseSettings(&frame, &settings)) { |
| 1323 HandleSettings(settings); | 1360 HandleSettings(settings); |
| 1324 spdy_settings_->Set(host_port_pair(), settings); | 1361 spdy_settings_->Set(host_port_pair(), settings); |
| 1325 } | 1362 } |
| 1326 | 1363 |
| 1327 received_settings_ = true; | 1364 received_settings_ = true; |
| 1328 | 1365 |
| 1329 net_log_.AddEvent( | 1366 net_log_.AddEvent( |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1448 switch (id) { | 1485 switch (id) { |
| 1449 case spdy::SETTINGS_MAX_CONCURRENT_STREAMS: | 1486 case spdy::SETTINGS_MAX_CONCURRENT_STREAMS: |
| 1450 max_concurrent_streams_ = std::min(static_cast<size_t>(val), | 1487 max_concurrent_streams_ = std::min(static_cast<size_t>(val), |
| 1451 max_concurrent_stream_limit_); | 1488 max_concurrent_stream_limit_); |
| 1452 ProcessPendingCreateStreams(); | 1489 ProcessPendingCreateStreams(); |
| 1453 break; | 1490 break; |
| 1454 } | 1491 } |
| 1455 } | 1492 } |
| 1456 } | 1493 } |
| 1457 | 1494 |
| 1495 int SpdySession::SendPing(spdy::SpdyStreamId stream_id) { | |
| 1496 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(10000); | |
| 1497 | |
| 1498 base::TimeTicks now = base::TimeTicks::Now(); | |
| 1499 // If there are no PINGs in flight and we haven't heard from server, then | |
| 1500 // send a pre-PING. | |
| 1501 if ((pings_in_flight_ == 0) && ((now - received_data_time_) > kInterval)) { | |
| 1502 int result = SendPrePing(stream_id); | |
| 1503 if (result != ERR_IO_PENDING) | |
| 1504 return result; | |
| 1505 } | |
| 1506 | |
| 1507 // Send a post-PING after a delay to make sure request has been received by | |
| 1508 // the server. | |
| 1509 const int kRequestTimeMs = 5000; | |
| 1510 if (!follower_ping_pending_) { | |
|
willchan no longer on Chromium
2011/10/13 15:47:17
What's the difference between a follower_ping and
ramant (doing other things)
2011/10/13 21:41:14
Used the word post_ping everywhere (sorry for usin
| |
| 1511 follower_ping_pending_ = true; | |
| 1512 MessageLoop::current()->PostDelayedTask( | |
| 1513 FROM_HERE, | |
| 1514 method_factory_.NewRunnableMethod( | |
| 1515 &SpdySession::SendPostPing, stream_id), | |
| 1516 kRequestTimeMs); | |
| 1517 | |
| 1518 // Post a task to check the status of the connection. | |
| 1519 const int kCheckStatusTimeMs = 10000; | |
| 1520 MessageLoop::current()->PostDelayedTask( | |
| 1521 FROM_HERE, | |
| 1522 method_factory_.NewRunnableMethod( | |
| 1523 &SpdySession::CheckStatus, stream_id, now), | |
| 1524 kCheckStatusTimeMs); | |
| 1525 } | |
| 1526 return ERR_IO_PENDING; | |
| 1527 } | |
| 1528 | |
| 1529 int SpdySession::SendPrePing(spdy::SpdyStreamId stream_id) { | |
| 1530 // Delay the writing of the PING frame so that it goes along with other | |
| 1531 // frames. | |
|
willchan no longer on Chromium
2011/10/13 15:47:17
What does this comment mean? What is supposed to h
ramant (doing other things)
2011/10/13 21:41:14
My intention is not to send PING frame as a separa
| |
| 1532 AutoReset<bool> reset(&delayed_write_pending_, true); | |
| 1533 return WritePingFrame(stream_id); | |
| 1534 } | |
| 1535 | |
| 1536 int SpdySession::SendPostPing(spdy::SpdyStreamId stream_id) { | |
| 1537 DCHECK(follower_ping_pending_); | |
| 1538 follower_ping_pending_ = false; | |
| 1539 return WritePingFrame(stream_id); | |
| 1540 } | |
| 1541 | |
| 1542 int SpdySession::WritePingFrame(spdy::SpdyStreamId stream_id) { | |
| 1543 // Find our stream. | |
| 1544 if (!IsStreamActive(stream_id)) | |
|
willchan no longer on Chromium
2011/10/13 15:47:17
Why is WritePingFrame() looking up the stream?
ramant (doing other things)
2011/10/13 21:41:14
Deleted the use of stream_id from all PING related
| |
| 1545 return ERR_INVALID_SPDY_STREAM; | |
| 1546 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; | |
| 1547 CHECK_EQ(stream->stream_id(), stream_id); | |
| 1548 | |
| 1549 scoped_ptr<spdy::SpdyPingControlFrame> ping_frame( | |
| 1550 spdy_framer_.CreatePingFrame(unique_id_counter_)); | |
| 1551 QueueFrame(ping_frame.get(), SPDY_PRIORITY_HIGHEST, NULL); | |
| 1552 | |
| 1553 if (net_log().IsLoggingAllEvents()) { | |
| 1554 net_log().AddEvent( | |
| 1555 NetLog::TYPE_SPDY_SESSION_PING, | |
| 1556 make_scoped_refptr(new NetLogSpdyPingParameter(unique_id_counter_))); | |
| 1557 } | |
| 1558 | |
| 1559 ++pings_in_flight_; | |
| 1560 unique_id_counter_ += 2; | |
| 1561 return ERR_IO_PENDING; | |
| 1562 } | |
| 1563 | |
| 1564 void SpdySession::CheckStatus(spdy::SpdyStreamId stream_id, | |
| 1565 base::TimeTicks last_check_time) { | |
| 1566 // Find our stream. | |
| 1567 if (!IsStreamActive(stream_id)) | |
| 1568 return; | |
| 1569 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; | |
| 1570 CHECK_EQ(stream->stream_id(), stream_id); | |
| 1571 | |
| 1572 // Check if we got a response back for all PINGs we had sent. | |
| 1573 if (pings_in_flight_ == 0) | |
| 1574 return; | |
| 1575 | |
| 1576 // Check if we haven't received any data in |kHungInterval|. | |
| 1577 const base::TimeDelta kHungInterval = base::TimeDelta::FromSeconds(10); | |
| 1578 if (received_data_time_ < last_check_time) { | |
| 1579 DCHECK(base::TimeTicks::Now() - received_data_time_ > kHungInterval); | |
| 1580 DeleteStream(stream_id, ERR_SPDY_PING_FAILED); | |
| 1581 return; | |
| 1582 } | |
| 1583 | |
| 1584 // Check the status of connection after a delay. | |
| 1585 base::TimeTicks now = base::TimeTicks::Now(); | |
| 1586 base::TimeDelta delay = now - received_data_time_ + kHungInterval; | |
|
willchan no longer on Chromium
2011/10/13 15:47:17
Is this math right? Shouldn't it be kHungInterval
ramant (doing other things)
2011/10/13 21:41:14
Done.
| |
| 1587 MessageLoop::current()->PostDelayedTask( | |
| 1588 FROM_HERE, | |
| 1589 method_factory_.NewRunnableMethod( | |
| 1590 &SpdySession::CheckStatus, stream_id, now), | |
| 1591 delay.InMilliseconds()); | |
| 1592 } | |
| 1593 | |
| 1458 void SpdySession::RecordHistograms() { | 1594 void SpdySession::RecordHistograms() { |
| 1459 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", | 1595 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", |
| 1460 streams_initiated_count_, | 1596 streams_initiated_count_, |
| 1461 0, 300, 50); | 1597 0, 300, 50); |
| 1462 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", | 1598 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", |
| 1463 streams_pushed_count_, | 1599 streams_pushed_count_, |
| 1464 0, 300, 50); | 1600 0, 300, 50); |
| 1465 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", | 1601 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", |
| 1466 streams_pushed_and_claimed_count_, | 1602 streams_pushed_and_claimed_count_, |
| 1467 0, 300, 50); | 1603 0, 300, 50); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1536 if (it == pending_callback_map_.end()) | 1672 if (it == pending_callback_map_.end()) |
| 1537 return; | 1673 return; |
| 1538 | 1674 |
| 1539 OldCompletionCallback* callback = it->second.callback; | 1675 OldCompletionCallback* callback = it->second.callback; |
| 1540 int result = it->second.result; | 1676 int result = it->second.result; |
| 1541 pending_callback_map_.erase(it); | 1677 pending_callback_map_.erase(it); |
| 1542 callback->Run(result); | 1678 callback->Run(result); |
| 1543 } | 1679 } |
| 1544 | 1680 |
| 1545 } // namespace net | 1681 } // namespace net |
| OLD | NEW |