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

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

Issue 8230037: Send PING to check the status of the SPDY connection. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/linked_ptr.h" 9 #include "base/memory/linked_ptr.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 } 165 }
166 166
167 private: 167 private:
168 ~NetLogSpdyRstParameter() {} 168 ~NetLogSpdyRstParameter() {}
169 const spdy::SpdyStreamId stream_id_; 169 const spdy::SpdyStreamId stream_id_;
170 const int status_; 170 const int status_;
171 171
172 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyRstParameter); 172 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyRstParameter);
173 }; 173 };
174 174
175 class NetLogSpdyPingParameter : public NetLog::EventParameters {
176 public:
177 explicit NetLogSpdyPingParameter(uint32 unique_id) : unique_id_(unique_id) {}
178
179 virtual Value* ToValue() const {
180 DictionaryValue* dict = new DictionaryValue();
181 dict->SetInteger("unique_id", unique_id_);
182 return dict;
183 }
184
185 private:
186 ~NetLogSpdyPingParameter() {}
187 const uint32 unique_id_;
188
189 DISALLOW_COPY_AND_ASSIGN(NetLogSpdyPingParameter);
190 };
191
175 class NetLogSpdyGoAwayParameter : public NetLog::EventParameters { 192 class NetLogSpdyGoAwayParameter : public NetLog::EventParameters {
176 public: 193 public:
177 NetLogSpdyGoAwayParameter(spdy::SpdyStreamId last_stream_id, 194 NetLogSpdyGoAwayParameter(spdy::SpdyStreamId last_stream_id,
178 int active_streams, 195 int active_streams,
179 int unclaimed_streams) 196 int unclaimed_streams)
180 : last_stream_id_(last_stream_id), 197 : last_stream_id_(last_stream_id),
181 active_streams_(active_streams), 198 active_streams_(active_streams),
182 unclaimed_streams_(unclaimed_streams) {} 199 unclaimed_streams_(unclaimed_streams) {}
183 200
184 virtual Value* ToValue() const { 201 virtual Value* ToValue() const {
(...skipping 21 matching lines...) Expand all
206 223
207 // static 224 // static
208 bool SpdySession::use_flow_control_ = false; 225 bool SpdySession::use_flow_control_ = false;
209 226
210 // static 227 // static
211 size_t SpdySession::init_max_concurrent_streams_ = 10; 228 size_t SpdySession::init_max_concurrent_streams_ = 10;
212 229
213 // static 230 // static
214 size_t SpdySession::max_concurrent_stream_limit_ = 256; 231 size_t SpdySession::max_concurrent_stream_limit_ = 256;
215 232
233 // static
234 bool SpdySession::enable_ping_based_connection_checking_ = true;
235
236 // static
237 int SpdySession::connection_at_risk_of_loss_ms_ = 0;
238
239 // static
240 int SpdySession::trailing_ping_delay_time_ms_ = 1000;
241
242 // static
243 int SpdySession::hung_interval_ms_ = 10000;
244
216 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, 245 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair,
217 SpdySessionPool* spdy_session_pool, 246 SpdySessionPool* spdy_session_pool,
218 SpdySettingsStorage* spdy_settings, 247 SpdySettingsStorage* spdy_settings,
219 bool verify_domain_authentication, 248 bool verify_domain_authentication,
220 NetLog* net_log) 249 NetLog* net_log)
221 : ALLOW_THIS_IN_INITIALIZER_LIST( 250 : ALLOW_THIS_IN_INITIALIZER_LIST(
222 read_callback_(this, &SpdySession::OnReadComplete)), 251 read_callback_(this, &SpdySession::OnReadComplete)),
223 ALLOW_THIS_IN_INITIALIZER_LIST( 252 ALLOW_THIS_IN_INITIALIZER_LIST(
224 write_callback_(this, &SpdySession::OnWriteComplete)), 253 write_callback_(this, &SpdySession::OnWriteComplete)),
225 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), 254 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
(...skipping 13 matching lines...) Expand all
239 max_concurrent_streams_(init_max_concurrent_streams_), 268 max_concurrent_streams_(init_max_concurrent_streams_),
240 streams_initiated_count_(0), 269 streams_initiated_count_(0),
241 streams_pushed_count_(0), 270 streams_pushed_count_(0),
242 streams_pushed_and_claimed_count_(0), 271 streams_pushed_and_claimed_count_(0),
243 streams_abandoned_count_(0), 272 streams_abandoned_count_(0),
244 frames_received_(0), 273 frames_received_(0),
245 bytes_received_(0), 274 bytes_received_(0),
246 sent_settings_(false), 275 sent_settings_(false),
247 received_settings_(false), 276 received_settings_(false),
248 stalled_streams_(0), 277 stalled_streams_(0),
278 pings_in_flight_(0),
279 next_ping_id_(1),
280 received_data_time_(base::TimeTicks::Now()),
281 trailing_ping_pending_(false),
282 check_ping_status_pending_(false),
283 last_sent_was_ping_(false),
249 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize), 284 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize),
250 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize), 285 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize),
251 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), 286 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)),
252 verify_domain_authentication_(verify_domain_authentication) { 287 verify_domain_authentication_(verify_domain_authentication) {
253 DCHECK(HttpStreamFactory::spdy_enabled()); 288 DCHECK(HttpStreamFactory::spdy_enabled());
254 net_log_.BeginEvent( 289 net_log_.BeginEvent(
255 NetLog::TYPE_SPDY_SESSION, 290 NetLog::TYPE_SPDY_SESSION,
256 make_scoped_refptr( 291 make_scoped_refptr(
257 new NetLogSpdySessionParameter(host_port_proxy_pair_))); 292 new NetLogSpdySessionParameter(host_port_proxy_pair_)));
258 293
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 spdy::SpdyStreamId stream_id, 502 spdy::SpdyStreamId stream_id,
468 RequestPriority priority, 503 RequestPriority priority,
469 spdy::SpdyControlFlags flags, 504 spdy::SpdyControlFlags flags,
470 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { 505 const linked_ptr<spdy::SpdyHeaderBlock>& headers) {
471 // Find our stream 506 // Find our stream
472 if (!IsStreamActive(stream_id)) 507 if (!IsStreamActive(stream_id))
473 return ERR_INVALID_SPDY_STREAM; 508 return ERR_INVALID_SPDY_STREAM;
474 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; 509 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id];
475 CHECK_EQ(stream->stream_id(), stream_id); 510 CHECK_EQ(stream->stream_id(), stream_id);
476 511
512 SendPrefacePingIfNoneInFlight();
513
477 scoped_ptr<spdy::SpdySynStreamControlFrame> syn_frame( 514 scoped_ptr<spdy::SpdySynStreamControlFrame> syn_frame(
478 spdy_framer_.CreateSynStream( 515 spdy_framer_.CreateSynStream(
479 stream_id, 0, 516 stream_id, 0,
480 ConvertRequestPriorityToSpdyPriority(priority), 517 ConvertRequestPriorityToSpdyPriority(priority),
481 flags, false, headers.get())); 518 flags, false, headers.get()));
482 QueueFrame(syn_frame.get(), priority, stream); 519 QueueFrame(syn_frame.get(), priority, stream);
483 520
484 base::StatsCounter spdy_requests("spdy.requests"); 521 base::StatsCounter spdy_requests("spdy.requests");
485 spdy_requests.Increment(); 522 spdy_requests.Increment();
486 streams_initiated_count_++; 523 streams_initiated_count_++;
487 524
488 if (net_log().IsLoggingAllEvents()) { 525 if (net_log().IsLoggingAllEvents()) {
489 net_log().AddEvent( 526 net_log().AddEvent(
490 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, 527 NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
491 make_scoped_refptr( 528 make_scoped_refptr(
492 new NetLogSpdySynParameter(headers, flags, stream_id, 0))); 529 new NetLogSpdySynParameter(headers, flags, stream_id, 0)));
493 } 530 }
531 last_sent_was_ping_ = false;
494 532
495 return ERR_IO_PENDING; 533 return ERR_IO_PENDING;
496 } 534 }
497 535
498 int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id, 536 int SpdySession::WriteStreamData(spdy::SpdyStreamId stream_id,
499 net::IOBuffer* data, int len, 537 net::IOBuffer* data, int len,
500 spdy::SpdyDataFlags flags) { 538 spdy::SpdyDataFlags flags) {
501 // Find our stream 539 // Find our stream
502 DCHECK(IsStreamActive(stream_id)); 540 DCHECK(IsStreamActive(stream_id));
503 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 541 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
504 CHECK_EQ(stream->stream_id(), stream_id); 542 CHECK_EQ(stream->stream_id(), stream_id);
505 if (!stream) 543 if (!stream)
506 return ERR_INVALID_SPDY_STREAM; 544 return ERR_INVALID_SPDY_STREAM;
507 545
546 SendPrefacePingIfNoneInFlight();
547
508 if (len > kMaxSpdyFrameChunkSize) { 548 if (len > kMaxSpdyFrameChunkSize) {
509 len = kMaxSpdyFrameChunkSize; 549 len = kMaxSpdyFrameChunkSize;
510 flags = static_cast<spdy::SpdyDataFlags>(flags & ~spdy::DATA_FLAG_FIN); 550 flags = static_cast<spdy::SpdyDataFlags>(flags & ~spdy::DATA_FLAG_FIN);
511 } 551 }
512 552
513 // Obey send window size of the stream if flow control is enabled. 553 // Obey send window size of the stream if flow control is enabled.
514 if (use_flow_control_) { 554 if (use_flow_control_) {
515 if (stream->send_window_size() <= 0) { 555 if (stream->send_window_size() <= 0) {
516 // Because we queue frames onto the session, it is possible that 556 // Because we queue frames onto the session, it is possible that
517 // a stream was not flow controlled at the time it attempted the 557 // a stream was not flow controlled at the time it attempted the
(...skipping 19 matching lines...) Expand all
537 if (net_log().IsLoggingAllEvents()) { 577 if (net_log().IsLoggingAllEvents()) {
538 net_log().AddEvent( 578 net_log().AddEvent(
539 NetLog::TYPE_SPDY_SESSION_SEND_DATA, 579 NetLog::TYPE_SPDY_SESSION_SEND_DATA,
540 make_scoped_refptr(new NetLogSpdyDataParameter(stream_id, len, flags))); 580 make_scoped_refptr(new NetLogSpdyDataParameter(stream_id, len, flags)));
541 } 581 }
542 582
543 // TODO(mbelshe): reduce memory copies here. 583 // TODO(mbelshe): reduce memory copies here.
544 scoped_ptr<spdy::SpdyDataFrame> frame( 584 scoped_ptr<spdy::SpdyDataFrame> frame(
545 spdy_framer_.CreateDataFrame(stream_id, data->data(), len, flags)); 585 spdy_framer_.CreateDataFrame(stream_id, data->data(), len, flags));
546 QueueFrame(frame.get(), stream->priority(), stream); 586 QueueFrame(frame.get(), stream->priority(), stream);
587 last_sent_was_ping_ = false;
547 return ERR_IO_PENDING; 588 return ERR_IO_PENDING;
548 } 589 }
549 590
550 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { 591 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) {
551 // TODO(mbelshe): We should send a RST_STREAM control frame here 592 // TODO(mbelshe): We should send a RST_STREAM control frame here
552 // so that the server can cancel a large send. 593 // so that the server can cancel a large send.
553 594
554 DeleteStream(stream_id, status); 595 DeleteStream(stream_id, status);
555 } 596 }
556 597
557 void SpdySession::ResetStream( 598 void SpdySession::ResetStream(
558 spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status) { 599 spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status) {
559 600
560 net_log().AddEvent( 601 net_log().AddEvent(
561 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, 602 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM,
562 make_scoped_refptr(new NetLogSpdyRstParameter(stream_id, status))); 603 make_scoped_refptr(new NetLogSpdyRstParameter(stream_id, status)));
563 604
564 scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame( 605 scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame(
565 spdy_framer_.CreateRstStream(stream_id, status)); 606 spdy_framer_.CreateRstStream(stream_id, status));
566 607
567 // Default to lowest priority unless we know otherwise. 608 // Default to lowest priority unless we know otherwise.
568 int priority = 3; 609 int priority = 3;
569 if(IsStreamActive(stream_id)) { 610 if(IsStreamActive(stream_id)) {
570 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 611 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
571 priority = stream->priority(); 612 priority = stream->priority();
572 } 613 }
573 QueueFrame(rst_frame.get(), priority, NULL); 614 QueueFrame(rst_frame.get(), priority, NULL);
574 615 last_sent_was_ping_ = false;
575 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); 616 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR);
576 } 617 }
577 618
578 bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const { 619 bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const {
579 return ContainsKey(active_streams_, stream_id); 620 return ContainsKey(active_streams_, stream_id);
580 } 621 }
581 622
582 LoadState SpdySession::GetLoadState() const { 623 LoadState SpdySession::GetLoadState() const {
583 // NOTE: The application only queries the LoadState via the 624 // NOTE: The application only queries the LoadState via the
584 // SpdyNetworkTransaction, and details are only needed when 625 // SpdyNetworkTransaction, and details are only needed when
(...skipping 20 matching lines...) Expand all
605 // Session is tearing down. 646 // Session is tearing down.
606 net::Error error = static_cast<net::Error>(bytes_read); 647 net::Error error = static_cast<net::Error>(bytes_read);
607 if (bytes_read == 0) 648 if (bytes_read == 0)
608 error = ERR_CONNECTION_CLOSED; 649 error = ERR_CONNECTION_CLOSED;
609 CloseSessionOnError(error, true); 650 CloseSessionOnError(error, true);
610 return; 651 return;
611 } 652 }
612 653
613 bytes_received_ += bytes_read; 654 bytes_received_ += bytes_read;
614 655
656 received_data_time_ = base::TimeTicks::Now();
657
615 // The SpdyFramer will use callbacks onto |this| as it parses frames. 658 // The SpdyFramer will use callbacks onto |this| as it parses frames.
616 // When errors occur, those callbacks can lead to teardown of all references 659 // 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 660 // to |this|, so maintain a reference to self during this call for safe
618 // cleanup. 661 // cleanup.
619 scoped_refptr<SpdySession> self(this); 662 scoped_refptr<SpdySession> self(this);
620 663
621 char *data = read_buffer_->data(); 664 char *data = read_buffer_->data();
622 while (bytes_read && 665 while (bytes_read &&
623 spdy_framer_.error_code() == spdy::SpdyFramer::SPDY_NO_ERROR) { 666 spdy_framer_.error_code() == spdy::SpdyFramer::SPDY_NO_ERROR) {
624 uint32 bytes_processed = spdy_framer_.ProcessInput(data, bytes_read); 667 uint32 bytes_processed = spdy_framer_.ProcessInput(data, bytes_read);
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 return; 1265 return;
1223 } 1266 }
1224 } 1267 }
1225 1268
1226 frames_received_++; 1269 frames_received_++;
1227 1270
1228 switch (type) { 1271 switch (type) {
1229 case spdy::GOAWAY: 1272 case spdy::GOAWAY:
1230 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame)); 1273 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame));
1231 break; 1274 break;
1275 case spdy::PING:
1276 OnPing(*reinterpret_cast<const spdy::SpdyPingControlFrame*>(frame));
1277 break;
1232 case spdy::SETTINGS: 1278 case spdy::SETTINGS:
1233 OnSettings( 1279 OnSettings(
1234 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); 1280 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame));
1235 break; 1281 break;
1236 case spdy::RST_STREAM: 1282 case spdy::RST_STREAM:
1237 OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); 1283 OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame));
1238 break; 1284 break;
1239 case spdy::SYN_STREAM: 1285 case spdy::SYN_STREAM:
1240 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), 1286 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame),
1241 headers); 1287 headers);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1310 CloseAllStreams(net::ERR_ABORTED); 1356 CloseAllStreams(net::ERR_ABORTED);
1311 1357
1312 // TODO(willchan): Cancel any streams that are past the GoAway frame's 1358 // TODO(willchan): Cancel any streams that are past the GoAway frame's
1313 // |last_accepted_stream_id|. 1359 // |last_accepted_stream_id|.
1314 1360
1315 // Don't bother killing any streams that are still reading. They'll either 1361 // 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 1362 // complete successfully or get an ERR_CONNECTION_CLOSED when the socket is
1317 // closed. 1363 // closed.
1318 } 1364 }
1319 1365
1366 void SpdySession::OnPing(const spdy::SpdyPingControlFrame& frame) {
1367 net_log_.AddEvent(
1368 NetLog::TYPE_SPDY_SESSION_PING,
1369 make_scoped_refptr(new NetLogSpdyPingParameter(frame.unique_id())));
1370
1371 // Send response to a PING from server.
1372 if (frame.unique_id() % 2 == 0) {
1373 WritePingFrame(frame.unique_id());
1374 return;
1375 }
1376
1377 --pings_in_flight_;
1378 if (pings_in_flight_ < 0) {
1379 CloseSessionOnError(net::ERR_SPDY_PROTOCOL_ERROR, true);
1380 return;
1381 }
1382
1383 if (pings_in_flight_ > 0)
1384 return;
1385
1386 if (last_sent_was_ping_)
1387 return;
1388
1389 PlanToSendTrailingPing();
1390 }
1391
1320 void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) { 1392 void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) {
1321 spdy::SpdySettings settings; 1393 spdy::SpdySettings settings;
1322 if (spdy_framer_.ParseSettings(&frame, &settings)) { 1394 if (spdy_framer_.ParseSettings(&frame, &settings)) {
1323 HandleSettings(settings); 1395 HandleSettings(settings);
1324 spdy_settings_->Set(host_port_pair(), settings); 1396 spdy_settings_->Set(host_port_pair(), settings);
1325 } 1397 }
1326 1398
1327 received_settings_ = true; 1399 received_settings_ = true;
1328 1400
1329 net_log_.AddEvent( 1401 net_log_.AddEvent(
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 CHECK_EQ(stream->stream_id(), stream_id); 1439 CHECK_EQ(stream->stream_id(), stream_id);
1368 1440
1369 net_log_.AddEvent( 1441 net_log_.AddEvent(
1370 NetLog::TYPE_SPDY_SESSION_RECV_WINDOW_UPDATE, 1442 NetLog::TYPE_SPDY_SESSION_RECV_WINDOW_UPDATE,
1371 make_scoped_refptr(new NetLogSpdyWindowUpdateParameter( 1443 make_scoped_refptr(new NetLogSpdyWindowUpdateParameter(
1372 stream_id, delta_window_size, stream->recv_window_size()))); 1444 stream_id, delta_window_size, stream->recv_window_size())));
1373 1445
1374 scoped_ptr<spdy::SpdyWindowUpdateControlFrame> window_update_frame( 1446 scoped_ptr<spdy::SpdyWindowUpdateControlFrame> window_update_frame(
1375 spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size)); 1447 spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size));
1376 QueueFrame(window_update_frame.get(), stream->priority(), stream); 1448 QueueFrame(window_update_frame.get(), stream->priority(), stream);
1449 last_sent_was_ping_ = false;
1377 } 1450 }
1378 1451
1379 // Given a cwnd that we would have sent to the server, modify it based on the 1452 // Given a cwnd that we would have sent to the server, modify it based on the
1380 // field trial policy. 1453 // field trial policy.
1381 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { 1454 uint32 ApplyCwndFieldTrialPolicy(int cwnd) {
1382 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); 1455 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd");
1383 if (!trial) { 1456 if (!trial) {
1384 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; 1457 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList";
1385 return cwnd; 1458 return cwnd;
1386 } 1459 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 1504
1432 net_log_.AddEvent( 1505 net_log_.AddEvent(
1433 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, 1506 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS,
1434 make_scoped_refptr(new NetLogSpdySettingsParameter(settings))); 1507 make_scoped_refptr(new NetLogSpdySettingsParameter(settings)));
1435 1508
1436 // Create the SETTINGS frame and send it. 1509 // Create the SETTINGS frame and send it.
1437 scoped_ptr<spdy::SpdySettingsControlFrame> settings_frame( 1510 scoped_ptr<spdy::SpdySettingsControlFrame> settings_frame(
1438 spdy_framer_.CreateSettings(settings)); 1511 spdy_framer_.CreateSettings(settings));
1439 sent_settings_ = true; 1512 sent_settings_ = true;
1440 QueueFrame(settings_frame.get(), 0, NULL); 1513 QueueFrame(settings_frame.get(), 0, NULL);
1514 last_sent_was_ping_ = false;
1441 } 1515 }
1442 1516
1443 void SpdySession::HandleSettings(const spdy::SpdySettings& settings) { 1517 void SpdySession::HandleSettings(const spdy::SpdySettings& settings) {
1444 for (spdy::SpdySettings::const_iterator i = settings.begin(), 1518 for (spdy::SpdySettings::const_iterator i = settings.begin(),
1445 end = settings.end(); i != end; ++i) { 1519 end = settings.end(); i != end; ++i) {
1446 const uint32 id = i->first.id(); 1520 const uint32 id = i->first.id();
1447 const uint32 val = i->second; 1521 const uint32 val = i->second;
1448 switch (id) { 1522 switch (id) {
1449 case spdy::SETTINGS_MAX_CONCURRENT_STREAMS: 1523 case spdy::SETTINGS_MAX_CONCURRENT_STREAMS:
1450 max_concurrent_streams_ = std::min(static_cast<size_t>(val), 1524 max_concurrent_streams_ = std::min(static_cast<size_t>(val),
1451 max_concurrent_stream_limit_); 1525 max_concurrent_stream_limit_);
1452 ProcessPendingCreateStreams(); 1526 ProcessPendingCreateStreams();
1453 break; 1527 break;
1454 } 1528 }
1455 } 1529 }
1456 } 1530 }
1457 1531
1532 void SpdySession::SendPrefacePingIfNoneInFlight() {
1533 if (pings_in_flight_ || trailing_ping_pending_ ||
1534 !enable_ping_based_connection_checking_)
1535 return;
1536
1537 const base::TimeDelta kConnectionAtRiskOfLoss =
1538 base::TimeDelta::FromMilliseconds(connection_at_risk_of_loss_ms_);
1539
1540 base::TimeTicks now = base::TimeTicks::Now();
1541 // If we haven't heard from server, then send a preface-PING.
1542 if ((now - received_data_time_) > kConnectionAtRiskOfLoss)
1543 SendPrefacePing();
1544
1545 PlanToSendTrailingPing();
1546 }
1547
1548 void SpdySession::SendPrefacePing() {
1549 WritePingFrame(next_ping_id_);
1550 }
1551
1552 void SpdySession::PlanToSendTrailingPing() {
1553 if (trailing_ping_pending_)
1554 return;
1555
1556 trailing_ping_pending_ = true;
1557 MessageLoop::current()->PostDelayedTask(
1558 FROM_HERE,
1559 method_factory_.NewRunnableMethod(&SpdySession::SendTrailingPing),
1560 trailing_ping_delay_time_ms_);
1561 }
1562
1563 void SpdySession::SendTrailingPing() {
1564 DCHECK(trailing_ping_pending_);
1565 trailing_ping_pending_ = false;
1566 WritePingFrame(next_ping_id_);
1567 }
1568
1569 void SpdySession::WritePingFrame(uint32 unique_id) {
1570 scoped_ptr<spdy::SpdyPingControlFrame> ping_frame(
1571 spdy_framer_.CreatePingFrame(next_ping_id_));
1572 QueueFrame(ping_frame.get(), SPDY_PRIORITY_HIGHEST, NULL);
1573
1574 if (net_log().IsLoggingAllEvents()) {
1575 net_log().AddEvent(
1576 NetLog::TYPE_SPDY_SESSION_PING,
1577 make_scoped_refptr(new NetLogSpdyPingParameter(next_ping_id_)));
1578 }
1579 if (unique_id % 2 != 0) {
1580 next_ping_id_ += 2;
1581 ++pings_in_flight_;
1582 last_sent_was_ping_ = true;
1583 PlanToCheckPingStatus();
1584 }
1585 }
1586
1587 void SpdySession::PlanToCheckPingStatus() {
1588 if (check_ping_status_pending_)
1589 return;
1590
1591 check_ping_status_pending_ = true;
1592 MessageLoop::current()->PostDelayedTask(
1593 FROM_HERE,
1594 method_factory_.NewRunnableMethod(
1595 &SpdySession::CheckPingStatus, base::TimeTicks::Now()),
1596 hung_interval_ms_);
1597 }
1598
1599 void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) {
1600 // Check if we got a response back for all PINGs we had sent.
1601 if (pings_in_flight_ == 0) {
1602 check_ping_status_pending_ = false;
1603 return;
1604 }
1605
1606 DCHECK(check_ping_status_pending_);
1607
1608 const base::TimeDelta kHungInterval =
1609 base::TimeDelta::FromMilliseconds(hung_interval_ms_);
1610
1611 base::TimeTicks now = base::TimeTicks::Now();
1612 base::TimeDelta delay = kHungInterval - (now - received_data_time_);
1613
1614 if (delay.InMilliseconds() < 0 || received_data_time_ < last_check_time) {
1615 DCHECK(now - received_data_time_ > kHungInterval);
1616 CloseSessionOnError(net::ERR_SPDY_PING_FAILED, true);
1617 return;
1618 }
1619
1620 // Check the status of connection after a delay.
1621 MessageLoop::current()->PostDelayedTask(
1622 FROM_HERE,
1623 method_factory_.NewRunnableMethod(&SpdySession::CheckPingStatus, now),
1624 delay.InMilliseconds());
1625 }
1626
1458 void SpdySession::RecordHistograms() { 1627 void SpdySession::RecordHistograms() {
1459 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", 1628 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession",
1460 streams_initiated_count_, 1629 streams_initiated_count_,
1461 0, 300, 50); 1630 0, 300, 50);
1462 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", 1631 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession",
1463 streams_pushed_count_, 1632 streams_pushed_count_,
1464 0, 300, 50); 1633 0, 300, 50);
1465 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", 1634 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession",
1466 streams_pushed_and_claimed_count_, 1635 streams_pushed_and_claimed_count_,
1467 0, 300, 50); 1636 0, 300, 50);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 if (it == pending_callback_map_.end()) 1705 if (it == pending_callback_map_.end())
1537 return; 1706 return;
1538 1707
1539 OldCompletionCallback* callback = it->second.callback; 1708 OldCompletionCallback* callback = it->second.callback;
1540 int result = it->second.result; 1709 int result = it->second.result;
1541 pending_callback_map_.erase(it); 1710 pending_callback_map_.erase(it);
1542 callback->Run(result); 1711 callback->Run(result);
1543 } 1712 }
1544 1713
1545 } // namespace net 1714 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698