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

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

Issue 10448083: Fix out of order SYN_STEAM frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 5 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 <map> 7 #include <map>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 173
174 NextProto g_default_protocol = kProtoUnknown; 174 NextProto g_default_protocol = kProtoUnknown;
175 size_t g_init_max_concurrent_streams = 100; 175 size_t g_init_max_concurrent_streams = 100;
176 size_t g_max_concurrent_stream_limit = 256; 176 size_t g_max_concurrent_stream_limit = 256;
177 size_t g_default_initial_rcv_window_size = 10 * 1024 * 1024; // 10MB 177 size_t g_default_initial_rcv_window_size = 10 * 1024 * 1024; // 10MB
178 bool g_enable_ping_based_connection_checking = true; 178 bool g_enable_ping_based_connection_checking = true;
179 179
180 } // namespace 180 } // namespace
181 181
182 // static 182 // static
183 void SpdySession::SpdyIOBufferProducer::ActivateStream(
184 SpdySession* spdy_session,
185 SpdyStream* spdy_stream) {
186 spdy_session->ActivateStream(spdy_stream);
187 }
188
189 // static
190 SpdyIOBuffer* SpdySession::SpdyIOBufferProducer::CreateIOBuffer(
191 SpdyFrame* frame,
192 RequestPriority priority,
193 SpdyStream* stream) {
194 size_t size = frame->length() + SpdyFrame::kHeaderSize;
195 DCHECK_GT(size, 0u);
196
197 // TODO(mbelshe): We have too much copying of data here.
198 IOBufferWithSize* buffer = new IOBufferWithSize(size);
199 memcpy(buffer->data(), frame->data(), size);
200
201 return new SpdyIOBuffer(buffer, size, priority, stream);
202 }
203
204 // static
183 void SpdySession::set_default_protocol(NextProto default_protocol) { 205 void SpdySession::set_default_protocol(NextProto default_protocol) {
184 g_default_protocol = default_protocol; 206 g_default_protocol = default_protocol;
185 } 207 }
186 208
187 // static 209 // static
188 void SpdySession::set_max_concurrent_streams(size_t value) { 210 void SpdySession::set_max_concurrent_streams(size_t value) {
189 g_max_concurrent_stream_limit = value; 211 g_max_concurrent_stream_limit = value;
190 } 212 }
191 213
192 // static 214 // static
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 370
349 SSLInfo ssl_info; 371 SSLInfo ssl_info;
350 bool was_npn_negotiated; 372 bool was_npn_negotiated;
351 NextProto protocol_negotiated = kProtoUnknown; 373 NextProto protocol_negotiated = kProtoUnknown;
352 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) 374 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated))
353 return true; // This is not a secure session, so all domains are okay. 375 return true; // This is not a secure session, so all domains are okay.
354 376
355 return !ssl_info.client_cert_sent && ssl_info.cert->VerifyNameMatch(domain); 377 return !ssl_info.client_cert_sent && ssl_info.cert->VerifyNameMatch(domain);
356 } 378 }
357 379
380 void SpdySession::SetStreamHasWriteAvailable(SpdyStream* stream) {
381 SpdyIOBufferProducer* producer = stream->CreateProducer();
382 write_queue_.push(producer);
383 stream_producers_[producer] = stream;
384 WriteSocketLater();
385 }
386
358 int SpdySession::GetPushStream( 387 int SpdySession::GetPushStream(
359 const GURL& url, 388 const GURL& url,
360 scoped_refptr<SpdyStream>* stream, 389 scoped_refptr<SpdyStream>* stream,
361 const BoundNetLog& stream_net_log) { 390 const BoundNetLog& stream_net_log) {
362 CHECK_NE(state_, CLOSED); 391 CHECK_NE(state_, CLOSED);
363 392
364 *stream = NULL; 393 *stream = NULL;
365 394
366 // Don't allow access to secure push streams over an unauthenticated, but 395 // Don't allow access to secure push streams over an unauthenticated, but
367 // encrypted SSL socket. 396 // encrypted SSL socket.
(...skipping 18 matching lines...) Expand all
386 return 0; 415 return 0;
387 } 416 }
388 417
389 int SpdySession::CreateStream( 418 int SpdySession::CreateStream(
390 const GURL& url, 419 const GURL& url,
391 RequestPriority priority, 420 RequestPriority priority,
392 scoped_refptr<SpdyStream>* spdy_stream, 421 scoped_refptr<SpdyStream>* spdy_stream,
393 const BoundNetLog& stream_net_log, 422 const BoundNetLog& stream_net_log,
394 const CompletionCallback& callback) { 423 const CompletionCallback& callback) {
395 if (!max_concurrent_streams_ || 424 if (!max_concurrent_streams_ ||
396 active_streams_.size() < max_concurrent_streams_) { 425 (active_streams_.size() + created_streams_.size()
426 < max_concurrent_streams_)) {
397 return CreateStreamImpl(url, priority, spdy_stream, stream_net_log); 427 return CreateStreamImpl(url, priority, spdy_stream, stream_net_log);
398 } 428 }
399 429
400 stalled_streams_++; 430 stalled_streams_++;
401 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS); 431 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS);
402 create_stream_queues_[priority].push( 432 create_stream_queues_[priority].push(
403 PendingCreateStream(url, priority, spdy_stream, 433 PendingCreateStream(url, priority, spdy_stream,
404 stream_net_log, callback)); 434 stream_net_log, callback));
405 return ERR_IO_PENDING; 435 return ERR_IO_PENDING;
406 } 436 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 CloseSessionOnError( 506 CloseSessionOnError(
477 static_cast<net::Error>(certificate_error_code_), 507 static_cast<net::Error>(certificate_error_code_),
478 true, 508 true,
479 "Tried to create SPDY stream for secure content over an " 509 "Tried to create SPDY stream for secure content over an "
480 "unauthenticated session."); 510 "unauthenticated session.");
481 return ERR_SPDY_PROTOCOL_ERROR; 511 return ERR_SPDY_PROTOCOL_ERROR;
482 } 512 }
483 513
484 const std::string& path = url.PathForRequest(); 514 const std::string& path = url.PathForRequest();
485 515
486 const SpdyStreamId stream_id = GetNewStreamId();
487
488 *spdy_stream = new SpdyStream(this, 516 *spdy_stream = new SpdyStream(this,
489 stream_id,
490 false, 517 false,
491 stream_net_log); 518 stream_net_log);
492 const scoped_refptr<SpdyStream>& stream = *spdy_stream; 519 const scoped_refptr<SpdyStream>& stream = *spdy_stream;
493 520
494 stream->set_priority(priority); 521 stream->set_priority(priority);
495 stream->set_path(path); 522 stream->set_path(path);
496 stream->set_send_window_size(initial_send_window_size_); 523 stream->set_send_window_size(initial_send_window_size_);
497 stream->set_recv_window_size(initial_recv_window_size_); 524 stream->set_recv_window_size(initial_recv_window_size_);
498 ActivateStream(stream); 525 created_streams_.insert(stream);
499 526
500 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount", 527 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount",
501 static_cast<int>(priority), 0, 10, 11); 528 static_cast<int>(priority), 0, 10, 11);
502 529
503 // TODO(mbelshe): Optimize memory allocations 530 // TODO(mbelshe): Optimize memory allocations
504 531
505 DCHECK_EQ(active_streams_[stream_id].get(), stream.get());
506 return OK; 532 return OK;
507 } 533 }
508 534
509 bool SpdySession::NeedsCredentials() const { 535 bool SpdySession::NeedsCredentials() const {
510 if (!is_secure_) 536 if (!is_secure_)
511 return false; 537 return false;
512 SSLClientSocket* ssl_socket = GetSSLClientSocket(); 538 SSLClientSocket* ssl_socket = GetSSLClientSocket();
513 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3) 539 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3)
514 return false; 540 return false;
515 return ssl_socket->WasDomainBoundCertSent(); 541 return ssl_socket->WasDomainBoundCertSent();
516 } 542 }
517 543
518 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) { 544 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) {
519 pooled_aliases_.insert(alias); 545 pooled_aliases_.insert(alias);
520 } 546 }
521 547
522 int SpdySession::GetProtocolVersion() const { 548 int SpdySession::GetProtocolVersion() const {
523 DCHECK(buffered_spdy_framer_.get()); 549 DCHECK(buffered_spdy_framer_.get());
524 return buffered_spdy_framer_->protocol_version(); 550 return buffered_spdy_framer_->protocol_version();
525 } 551 }
526 552
527 int SpdySession::WriteSynStream( 553 SpdySynStreamControlFrame* SpdySession::CreateSynStream(
528 SpdyStreamId stream_id, 554 SpdyStreamId stream_id,
529 RequestPriority priority, 555 RequestPriority priority,
530 uint8 credential_slot, 556 uint8 credential_slot,
531 SpdyControlFlags flags, 557 SpdyControlFlags flags,
532 const linked_ptr<SpdyHeaderBlock>& headers) { 558 const linked_ptr<SpdyHeaderBlock>& headers) {
533 // Find our stream 559 CHECK(IsStreamActive(stream_id));
534 if (!IsStreamActive(stream_id))
535 return ERR_INVALID_SPDY_STREAM;
536 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; 560 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id];
537 CHECK_EQ(stream->stream_id(), stream_id); 561 CHECK_EQ(stream->stream_id(), stream_id);
538 562
539 SendPrefacePingIfNoneInFlight(); 563 SendPrefacePingIfNoneInFlight();
540 564
541 DCHECK(buffered_spdy_framer_.get()); 565 DCHECK(buffered_spdy_framer_.get());
542 scoped_ptr<SpdySynStreamControlFrame> syn_frame( 566 scoped_ptr<SpdySynStreamControlFrame> syn_frame(
543 buffered_spdy_framer_->CreateSynStream( 567 buffered_spdy_framer_->CreateSynStream(
544 stream_id, 0, 568 stream_id, 0,
545 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), 569 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()),
546 credential_slot, flags, false, headers.get())); 570 credential_slot, flags, true, headers.get()));
547 // We enqueue all SYN_STREAM frames at the same priority to ensure
548 // that we do not send them out-of-order.
549 // http://crbug.com/111708
550 QueueFrame(syn_frame.get(), HIGHEST, stream);
551 571
552 base::StatsCounter spdy_requests("spdy.requests"); 572 base::StatsCounter spdy_requests("spdy.requests");
553 spdy_requests.Increment(); 573 spdy_requests.Increment();
554 streams_initiated_count_++; 574 streams_initiated_count_++;
555 575
556 if (net_log().IsLoggingAllEvents()) { 576 if (net_log().IsLoggingAllEvents()) {
557 net_log().AddEvent( 577 net_log().AddEvent(
558 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, 578 NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
559 base::Bind(&NetLogSpdySynCallback, headers.get(), flags, stream_id, 0)); 579 base::Bind(&NetLogSpdySynCallback, headers.get(), flags, stream_id, 0));
560 } 580 }
561 581
562 return ERR_IO_PENDING; 582 return syn_frame.release();
563 } 583 }
564 584
565 int SpdySession::WriteCredentialFrame(const std::string& origin, 585 SpdyCredentialControlFrame* SpdySession::CreateCredentialFrame(
566 SSLClientCertType type, 586 const std::string& origin,
567 const std::string& key, 587 SSLClientCertType type,
568 const std::string& cert, 588 const std::string& key,
569 RequestPriority priority) { 589 const std::string& cert,
590 RequestPriority priority) {
570 DCHECK(is_secure_); 591 DCHECK(is_secure_);
571 unsigned char secret[32]; // 32 bytes from the spec 592 unsigned char secret[32]; // 32 bytes from the spec
572 GetSSLClientSocket()->ExportKeyingMaterial("SPDY certificate proof", 593 GetSSLClientSocket()->ExportKeyingMaterial("SPDY certificate proof",
573 true, origin, 594 true, origin,
574 secret, arraysize(secret)); 595 secret, arraysize(secret));
575 596
576 // Convert the key string into a vector<unit8> 597 // Convert the key string into a vector<unit8>
577 std::vector<uint8> key_data; 598 std::vector<uint8> key_data;
578 for (size_t i = 0; i < key.length(); i++) { 599 for (size_t i = 0; i < key.length(); i++) {
579 key_data.push_back(key[i]); 600 key_data.push_back(key[i]);
(...skipping 21 matching lines...) Expand all
601 SpdyCredential credential; 622 SpdyCredential credential;
602 GURL origin_url(origin); 623 GURL origin_url(origin);
603 credential.slot = 624 credential.slot =
604 credential_state_.SetHasCredential(origin_url); 625 credential_state_.SetHasCredential(origin_url);
605 credential.certs.push_back(cert); 626 credential.certs.push_back(cert);
606 credential.proof.assign(proof.begin(), proof.end()); 627 credential.proof.assign(proof.begin(), proof.end());
607 628
608 DCHECK(buffered_spdy_framer_.get()); 629 DCHECK(buffered_spdy_framer_.get());
609 scoped_ptr<SpdyCredentialControlFrame> credential_frame( 630 scoped_ptr<SpdyCredentialControlFrame> credential_frame(
610 buffered_spdy_framer_->CreateCredentialFrame(credential)); 631 buffered_spdy_framer_->CreateCredentialFrame(credential));
611 // We enqueue all SYN_STREAM frames at the same priority to ensure
612 // that we do not send them out-of-order, which means that we need
613 // to enqueue all CREDENTIAL frames at this priority to ensure that
614 // they are sent *before* the SYN_STREAM that references them.
615 // http://crbug.com/111708
616 QueueFrame(credential_frame.get(), HIGHEST, NULL);
617 632
618 if (net_log().IsLoggingAllEvents()) { 633 if (net_log().IsLoggingAllEvents()) {
619 net_log().AddEvent( 634 net_log().AddEvent(
620 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL, 635 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL,
621 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin)); 636 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin));
622 } 637 }
623 return ERR_IO_PENDING; 638 return credential_frame.release();
624 } 639 }
625 640
626 int SpdySession::WriteStreamData(SpdyStreamId stream_id, 641 SpdyDataFrame* SpdySession::CreateDataFrame(SpdyStreamId stream_id,
627 net::IOBuffer* data, int len, 642 net::IOBuffer* data, int len,
628 SpdyDataFlags flags) { 643 SpdyDataFlags flags) {
629 // Find our stream 644 // Find our stream
630 CHECK(IsStreamActive(stream_id)); 645 CHECK(IsStreamActive(stream_id));
631 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 646 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
632 CHECK_EQ(stream->stream_id(), stream_id); 647 CHECK_EQ(stream->stream_id(), stream_id);
633 648
634 if (len > kMaxSpdyFrameChunkSize) { 649 if (len > kMaxSpdyFrameChunkSize) {
635 len = kMaxSpdyFrameChunkSize; 650 len = kMaxSpdyFrameChunkSize;
636 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); 651 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN);
637 } 652 }
638 653
639 // Obey send window size of the stream if flow control is enabled. 654 // Obey send window size of the stream if flow control is enabled.
640 if (flow_control_) { 655 if (flow_control_) {
641 if (stream->send_window_size() <= 0) { 656 if (stream->send_window_size() <= 0) {
642 // Because we queue frames onto the session, it is possible that 657 // Because we queue frames onto the session, it is possible that
643 // a stream was not flow controlled at the time it attempted the 658 // a stream was not flow controlled at the time it attempted the
644 // write, but when we go to fulfill the write, it is now flow 659 // write, but when we go to fulfill the write, it is now flow
645 // controlled. This is why we need the session to mark the stream 660 // controlled. This is why we need the session to mark the stream
646 // as stalled - because only the session knows for sure when the 661 // as stalled - because only the session knows for sure when the
647 // stall occurs. 662 // stall occurs.
648 stream->set_stalled_by_flow_control(true); 663 stream->set_stalled_by_flow_control(true);
649 net_log().AddEvent( 664 net_log().AddEvent(
650 NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW, 665 NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW,
651 NetLog::IntegerCallback("stream_id", stream_id)); 666 NetLog::IntegerCallback("stream_id", stream_id));
652 return ERR_IO_PENDING; 667 return NULL;
653 } 668 }
654 int new_len = std::min(len, stream->send_window_size()); 669 int new_len = std::min(len, stream->send_window_size());
655 if (new_len < len) { 670 if (new_len < len) {
656 len = new_len; 671 len = new_len;
657 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); 672 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN);
658 } 673 }
659 stream->DecreaseSendWindowSize(len); 674 stream->DecreaseSendWindowSize(len);
660 } 675 }
661 676
662 if (net_log().IsLoggingAllEvents()) { 677 if (net_log().IsLoggingAllEvents()) {
663 net_log().AddEvent( 678 net_log().AddEvent(
664 NetLog::TYPE_SPDY_SESSION_SEND_DATA, 679 NetLog::TYPE_SPDY_SESSION_SEND_DATA,
665 base::Bind(&NetLogSpdyDataCallback, stream_id, len, flags)); 680 base::Bind(&NetLogSpdyDataCallback, stream_id, len, flags));
666 } 681 }
667 682
668 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. 683 // Send PrefacePing for DATA_FRAMEs with nonzero payload size.
669 if (len > 0) 684 if (len > 0)
670 SendPrefacePingIfNoneInFlight(); 685 SendPrefacePingIfNoneInFlight();
671 686
672 // TODO(mbelshe): reduce memory copies here. 687 // TODO(mbelshe): reduce memory copies here.
673 DCHECK(buffered_spdy_framer_.get()); 688 DCHECK(buffered_spdy_framer_.get());
674 scoped_ptr<SpdyDataFrame> frame( 689 scoped_ptr<SpdyDataFrame> frame(
675 buffered_spdy_framer_->CreateDataFrame( 690 buffered_spdy_framer_->CreateDataFrame(
676 stream_id, data->data(), len, flags)); 691 stream_id, data->data(), len, flags));
677 QueueFrame(frame.get(), stream->priority(), stream);
678 692
679 return ERR_IO_PENDING; 693 return frame.release();
680 } 694 }
681 695
682 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { 696 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) {
697 DCHECK_NE(0u, stream_id);
683 // TODO(mbelshe): We should send a RST_STREAM control frame here 698 // TODO(mbelshe): We should send a RST_STREAM control frame here
684 // so that the server can cancel a large send. 699 // so that the server can cancel a large send.
685 700
686 DeleteStream(stream_id, status); 701 DeleteStream(stream_id, status);
687 } 702 }
688 703
704 void SpdySession::CloseCreatedStream(SpdyStream* stream, int status) {
705 DCHECK_EQ(0u, stream->stream_id());
706 created_streams_.erase(scoped_refptr<SpdyStream>(stream));
707 }
708
689 void SpdySession::ResetStream(SpdyStreamId stream_id, 709 void SpdySession::ResetStream(SpdyStreamId stream_id,
690 SpdyStatusCodes status, 710 SpdyStatusCodes status,
691 const std::string& description) { 711 const std::string& description) {
692 net_log().AddEvent( 712 net_log().AddEvent(
693 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, 713 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM,
694 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); 714 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description));
695 715
696 DCHECK(buffered_spdy_framer_.get()); 716 DCHECK(buffered_spdy_framer_.get());
697 scoped_ptr<SpdyRstStreamControlFrame> rst_frame( 717 scoped_ptr<SpdyRstStreamControlFrame> rst_frame(
698 buffered_spdy_framer_->CreateRstStream(stream_id, status)); 718 buffered_spdy_framer_->CreateRstStream(stream_id, status));
699 719
700 // Default to lowest priority unless we know otherwise. 720 // Default to lowest priority unless we know otherwise.
701 RequestPriority priority = net::IDLE; 721 RequestPriority priority = net::IDLE;
702 if(IsStreamActive(stream_id)) { 722 if(IsStreamActive(stream_id)) {
703 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 723 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
704 priority = stream->priority(); 724 priority = stream->priority();
705 } 725 }
706 QueueFrame(rst_frame.get(), priority, NULL); 726 QueueFrame(rst_frame.release(), priority);
707 RecordProtocolErrorHistogram( 727 RecordProtocolErrorHistogram(
708 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); 728 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID));
709 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); 729 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR);
710 } 730 }
711 731
712 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { 732 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const {
713 return ContainsKey(active_streams_, stream_id); 733 return ContainsKey(active_streams_, stream_id);
714 } 734 }
715 735
716 LoadState SpdySession::GetLoadState() const { 736 LoadState SpdySession::GetLoadState() const {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 // closed, just return. 904 // closed, just return.
885 if (state_ < CONNECTED || state_ == CLOSED) 905 if (state_ < CONNECTED || state_ == CLOSED)
886 return; 906 return;
887 907
888 if (write_pending_) // Another write is in progress still. 908 if (write_pending_) // Another write is in progress still.
889 return; 909 return;
890 910
891 // Loop sending frames until we've sent everything or until the write 911 // Loop sending frames until we've sent everything or until the write
892 // returns error (or ERR_IO_PENDING). 912 // returns error (or ERR_IO_PENDING).
893 DCHECK(buffered_spdy_framer_.get()); 913 DCHECK(buffered_spdy_framer_.get());
894 while (in_flight_write_.buffer() || !queue_.empty()) { 914 while (in_flight_write_.buffer() || !write_queue_.empty()) {
895 if (!in_flight_write_.buffer()) { 915 if (!in_flight_write_.buffer()) {
896 // Grab the next SpdyFrame to send. 916 // Grab the next SpdyBuffer to send.
897 SpdyIOBuffer next_buffer = queue_.top(); 917 scoped_ptr<SpdyIOBufferProducer> producer(write_queue_.top());
898 queue_.pop(); 918 scoped_ptr<SpdyIOBuffer> buffer(producer->ProduceNextBuffer(this));
919 stream_producers_.erase(producer.get());
920 write_queue_.pop();
921 // It is possible that a stream had data to write, but a
922 // WINDOW_UPDATE frame has been received which made that
923 // stream no longer writable.
924 // TODO(rch): consider handling that case by removing the
925 // stream from the writable queue?
926 if (buffer == NULL)
927 continue;
899 928
900 // We've deferred compression until just before we write it to the socket, 929 in_flight_write_ = *buffer;
901 // which is now. At this time, we don't compress our data frames.
902 SpdyFrame uncompressed_frame(next_buffer.buffer()->data(), false);
903 size_t size;
904 if (buffered_spdy_framer_->IsCompressible(uncompressed_frame)) {
905 DCHECK(uncompressed_frame.is_control_frame());
906 const SpdyControlFrame* uncompressed_control_frame =
907 reinterpret_cast<const SpdyControlFrame*>(&uncompressed_frame);
908 scoped_ptr<SpdyFrame> compressed_frame(
909 buffered_spdy_framer_->CompressControlFrame(
910 *uncompressed_control_frame));
911 if (!compressed_frame.get()) {
912 RecordProtocolErrorHistogram(
913 PROTOCOL_ERROR_SPDY_COMPRESSION_FAILURE);
914 CloseSessionOnError(
915 net::ERR_SPDY_PROTOCOL_ERROR, true, "SPDY Compression failure.");
916 return;
917 }
918
919 size = compressed_frame->length() + SpdyFrame::kHeaderSize;
920
921 DCHECK_GT(size, 0u);
922
923 // TODO(mbelshe): We have too much copying of data here.
924 IOBufferWithSize* buffer = new IOBufferWithSize(size);
925 memcpy(buffer->data(), compressed_frame->data(), size);
926
927 // Attempt to send the frame.
928 in_flight_write_ = SpdyIOBuffer(buffer, size, HIGHEST,
929 next_buffer.stream());
930 } else {
931 size = uncompressed_frame.length() + SpdyFrame::kHeaderSize;
932 in_flight_write_ = next_buffer;
933 }
934 } else { 930 } else {
935 DCHECK(in_flight_write_.buffer()->BytesRemaining()); 931 DCHECK(in_flight_write_.buffer()->BytesRemaining());
936 } 932 }
937 933
938 write_pending_ = true; 934 write_pending_ = true;
939 int rv = connection_->socket()->Write( 935 int rv = connection_->socket()->Write(
940 in_flight_write_.buffer(), 936 in_flight_write_.buffer(),
941 in_flight_write_.buffer()->BytesRemaining(), 937 in_flight_write_.buffer()->BytesRemaining(),
942 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this))); 938 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this)));
943 if (rv == net::ERR_IO_PENDING) 939 if (rv == net::ERR_IO_PENDING)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 while (!active_streams_.empty()) { 973 while (!active_streams_.empty()) {
978 ActiveStreamMap::iterator it = active_streams_.begin(); 974 ActiveStreamMap::iterator it = active_streams_.begin();
979 const scoped_refptr<SpdyStream>& stream = it->second; 975 const scoped_refptr<SpdyStream>& stream = it->second;
980 DCHECK(stream); 976 DCHECK(stream);
981 std::string description = base::StringPrintf( 977 std::string description = base::StringPrintf(
982 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); 978 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path();
983 stream->LogStreamError(status, description); 979 stream->LogStreamError(status, description);
984 DeleteStream(stream->stream_id(), status); 980 DeleteStream(stream->stream_id(), status);
985 } 981 }
986 982
983 while (!created_streams_.empty()) {
984 CreatedStreamSet::iterator it = created_streams_.begin();
985 const scoped_refptr<SpdyStream>& stream = *it;
986 std::string description = base::StringPrintf(
987 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path();
988 stream->LogStreamError(status, description);
989 stream->OnClose(status);
990 created_streams_.erase(it);
991 }
992
987 // We also need to drain the queue. 993 // We also need to drain the queue.
988 while (queue_.size()) 994 while (!write_queue_.empty()) {
989 queue_.pop(); 995 SpdyIOBufferProducer* producer = write_queue_.top();
996 stream_producers_.erase(producer);
997 delete producer;
998 write_queue_.pop();
999 }
990 } 1000 }
991 1001
992 int SpdySession::GetNewStreamId() { 1002 int SpdySession::GetNewStreamId() {
993 int id = stream_hi_water_mark_; 1003 int id = stream_hi_water_mark_;
994 stream_hi_water_mark_ += 2; 1004 stream_hi_water_mark_ += 2;
995 if (stream_hi_water_mark_ > 0x7fff) 1005 if (stream_hi_water_mark_ > 0x7fff)
996 stream_hi_water_mark_ = 1; 1006 stream_hi_water_mark_ = 1;
997 return id; 1007 return id;
998 } 1008 }
999 1009
1000 void SpdySession::QueueFrame(SpdyFrame* frame,
1001 RequestPriority priority,
1002 SpdyStream* stream) {
1003 int length = SpdyFrame::kHeaderSize + frame->length();
1004 IOBuffer* buffer = new IOBuffer(length);
1005 memcpy(buffer->data(), frame->data(), length);
1006 queue_.push(SpdyIOBuffer(buffer, length, priority, stream));
1007
1008 WriteSocketLater();
1009 }
1010
1011 void SpdySession::CloseSessionOnError(net::Error err, 1010 void SpdySession::CloseSessionOnError(net::Error err,
1012 bool remove_from_pool, 1011 bool remove_from_pool,
1013 const std::string& description) { 1012 const std::string& description) {
1014 // Closing all streams can have a side-effect of dropping the last reference 1013 // Closing all streams can have a side-effect of dropping the last reference
1015 // to |this|. Hold a reference through this function. 1014 // to |this|. Hold a reference through this function.
1016 scoped_refptr<SpdySession> self(this); 1015 scoped_refptr<SpdySession> self(this);
1017 1016
1018 DCHECK_LT(err, OK); 1017 DCHECK_LT(err, OK);
1019 net_log_.AddEvent( 1018 net_log_.AddEvent(
1020 NetLog::TYPE_SPDY_SESSION_CLOSE, 1019 NetLog::TYPE_SPDY_SESSION_CLOSE,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 return connection_->socket()->GetPeerAddress(address); 1089 return connection_->socket()->GetPeerAddress(address);
1091 } 1090 }
1092 1091
1093 int SpdySession::GetLocalAddress(IPEndPoint* address) const { 1092 int SpdySession::GetLocalAddress(IPEndPoint* address) const {
1094 if (!connection_->socket()) 1093 if (!connection_->socket())
1095 return ERR_SOCKET_NOT_CONNECTED; 1094 return ERR_SOCKET_NOT_CONNECTED;
1096 1095
1097 return connection_->socket()->GetLocalAddress(address); 1096 return connection_->socket()->GetLocalAddress(address);
1098 } 1097 }
1099 1098
1099 class SimpleSpdyIOBufferProducer : public SpdySession::SpdyIOBufferProducer {
1100 public:
1101 SimpleSpdyIOBufferProducer(SpdyFrame* frame,
1102 RequestPriority priority)
1103 : frame_(frame),
1104 priority_(priority) {
1105 }
1106
1107 virtual RequestPriority GetPriority() const OVERRIDE {
1108 return priority_;
1109 }
1110
1111 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) {
1112 return SpdySession::SpdyIOBufferProducer::CreateIOBuffer(
1113 frame_, priority_, NULL);
1114 }
1115
1116 private:
1117 SpdyFrame* frame_;
1118 RequestPriority priority_;
1119 };
1120
1121 void SpdySession::QueueFrame(SpdyFrame* frame,
1122 RequestPriority priority) {
1123 SimpleSpdyIOBufferProducer* producer
1124 = new SimpleSpdyIOBufferProducer(frame, priority);
1125 write_queue_.push(producer);
1126 WriteSocketLater();
1127 }
1128
1100 void SpdySession::ActivateStream(SpdyStream* stream) { 1129 void SpdySession::ActivateStream(SpdyStream* stream) {
1130 if (stream->stream_id() == 0) {
1131 stream->set_stream_id(GetNewStreamId());
1132 created_streams_.erase(scoped_refptr<SpdyStream>(stream));
1133 }
1101 const SpdyStreamId id = stream->stream_id(); 1134 const SpdyStreamId id = stream->stream_id();
1102 DCHECK(!IsStreamActive(id)); 1135 DCHECK(!IsStreamActive(id));
1103 1136
1104 active_streams_[id] = stream; 1137 active_streams_[id] = stream;
1105 } 1138 }
1106 1139
1107 void SpdySession::DeleteStream(SpdyStreamId id, int status) { 1140 void SpdySession::DeleteStream(SpdyStreamId id, int status) {
1108 // For push streams, if they are being deleted normally, we leave 1141 // For push streams, if they are being deleted normally, we leave
1109 // the stream in the unclaimed_pushed_streams_ list. However, if 1142 // the stream in the unclaimed_pushed_streams_ list. However, if
1110 // the stream is errored out, clean it up entirely. 1143 // the stream is errored out, clean it up entirely.
1111 if (status != OK) { 1144 if (status != OK) {
1112 PushedStreamMap::iterator it; 1145 PushedStreamMap::iterator it;
1113 for (it = unclaimed_pushed_streams_.begin(); 1146 for (it = unclaimed_pushed_streams_.begin();
1114 it != unclaimed_pushed_streams_.end(); ++it) { 1147 it != unclaimed_pushed_streams_.end(); ++it) {
1115 scoped_refptr<SpdyStream> curr = it->second; 1148 scoped_refptr<SpdyStream> curr = it->second;
1116 if (id == curr->stream_id()) { 1149 if (id == curr->stream_id()) {
1117 unclaimed_pushed_streams_.erase(it); 1150 unclaimed_pushed_streams_.erase(it);
1118 break; 1151 break;
1119 } 1152 }
1120 } 1153 }
1121 } 1154 }
1122 1155
1123 // The stream might have been deleted. 1156 // The stream might have been deleted.
1124 ActiveStreamMap::iterator it2 = active_streams_.find(id); 1157 ActiveStreamMap::iterator it2 = active_streams_.find(id);
1125 if (it2 == active_streams_.end()) 1158 if (it2 == active_streams_.end())
1126 return; 1159 return;
1127 1160
1161 // Possibly remove from the write queue.
1162 WriteQueue old = write_queue_;
1163 write_queue_ = WriteQueue();
1164 while (!old.empty()) {
1165 SpdyIOBufferProducer* producer = old.top();
1166 StreamProducerMap::iterator it = stream_producers_.find(producer);
1167 if (it == stream_producers_.end() || it->second->stream_id() != id)
1168 write_queue_.push(producer);
1169 else
1170 delete producer;
1171 old.pop();
1172 }
1173
1128 // If this is an active stream, call the callback. 1174 // If this is an active stream, call the callback.
1129 const scoped_refptr<SpdyStream> stream(it2->second); 1175 const scoped_refptr<SpdyStream> stream(it2->second);
1130 active_streams_.erase(it2); 1176 active_streams_.erase(it2);
1131 if (stream) 1177 if (stream)
1132 stream->OnClose(status); 1178 stream->OnClose(status);
1133 ProcessPendingCreateStreams(); 1179 ProcessPendingCreateStreams();
1134 } 1180 }
1135 1181
1136 void SpdySession::RemoveFromPool() { 1182 void SpdySession::RemoveFromPool() {
1137 if (spdy_session_pool_) { 1183 if (spdy_session_pool_) {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 } 1393 }
1348 1394
1349 // There should not be an existing pushed stream with the same path. 1395 // There should not be an existing pushed stream with the same path.
1350 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url); 1396 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url);
1351 if (it != unclaimed_pushed_streams_.end()) { 1397 if (it != unclaimed_pushed_streams_.end()) {
1352 ResetStream(stream_id, PROTOCOL_ERROR, 1398 ResetStream(stream_id, PROTOCOL_ERROR,
1353 "Received duplicate pushed stream with url: " + url); 1399 "Received duplicate pushed stream with url: " + url);
1354 return; 1400 return;
1355 } 1401 }
1356 1402
1357 scoped_refptr<SpdyStream> stream( 1403 scoped_refptr<SpdyStream> stream(new SpdyStream(this, true, net_log_));
1358 new SpdyStream(this, stream_id, true, net_log_)); 1404 stream->set_stream_id(stream_id);
1359 1405
1360 stream->set_path(gurl.PathForRequest()); 1406 stream->set_path(gurl.PathForRequest());
1361 stream->set_send_window_size(initial_send_window_size_); 1407 stream->set_send_window_size(initial_send_window_size_);
1362 stream->set_recv_window_size(initial_recv_window_size_); 1408 stream->set_recv_window_size(initial_recv_window_size_);
1363 1409
1364 unclaimed_pushed_streams_[url] = stream; 1410 unclaimed_pushed_streams_[url] = stream;
1365 1411
1366 ActivateStream(stream); 1412 ActivateStream(stream);
1367 stream->set_response_received(); 1413 stream->set_response_received();
1368 1414
1369 // Parse the headers. 1415 // Parse the headers.
1370 if (!Respond(*headers, stream)) 1416 if (!Respond(*headers, stream))
1371 return; 1417 return;
1372 1418
1373 base::StatsCounter push_requests("spdy.pushed_streams"); 1419 base::StatsCounter push_requests("spdy.pushed_streams");
1374 push_requests.Increment(); 1420 push_requests.Increment();
1375 } 1421 }
1376 1422
1377 void SpdySession::OnSynReply(const SpdySynReplyControlFrame& frame, 1423 void SpdySession::OnSynReply(const SpdySynReplyControlFrame& frame,
1378 const linked_ptr<SpdyHeaderBlock>& headers) { 1424 const linked_ptr<SpdyHeaderBlock>& headers) {
1379 SpdyStreamId stream_id = frame.stream_id(); 1425 SpdyStreamId stream_id = frame.stream_id();
1380
1381 if (net_log().IsLoggingAllEvents()) { 1426 if (net_log().IsLoggingAllEvents()) {
1382 net_log().AddEvent( 1427 net_log().AddEvent(
1383 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, 1428 NetLog::TYPE_SPDY_SESSION_SYN_REPLY,
1384 base::Bind(&NetLogSpdySynCallback, 1429 base::Bind(&NetLogSpdySynCallback,
1385 headers.get(), static_cast<SpdyControlFlags>(frame.flags()), 1430 headers.get(), static_cast<SpdyControlFlags>(frame.flags()),
1386 stream_id, 0)); 1431 stream_id, 0));
1387 } 1432 }
1388 1433
1389 if (!IsStreamActive(stream_id)) { 1434 if (!IsStreamActive(stream_id)) {
1390 // NOTE: it may just be that the stream was cancelled. 1435 // NOTE: it may just be that the stream was cancelled.
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1554 CHECK_EQ(stream->stream_id(), stream_id); 1599 CHECK_EQ(stream->stream_id(), stream_id);
1555 1600
1556 net_log_.AddEvent( 1601 net_log_.AddEvent(
1557 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE, 1602 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE,
1558 base::Bind(&NetLogSpdyWindowUpdateCallback, 1603 base::Bind(&NetLogSpdyWindowUpdateCallback,
1559 stream_id, delta_window_size)); 1604 stream_id, delta_window_size));
1560 1605
1561 DCHECK(buffered_spdy_framer_.get()); 1606 DCHECK(buffered_spdy_framer_.get());
1562 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame( 1607 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame(
1563 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); 1608 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size));
1564 QueueFrame(window_update_frame.get(), stream->priority(), NULL); 1609 QueueFrame(window_update_frame.release(), stream->priority());
1565 } 1610 }
1566 1611
1567 // Given a cwnd that we would have sent to the server, modify it based on the 1612 // Given a cwnd that we would have sent to the server, modify it based on the
1568 // field trial policy. 1613 // field trial policy.
1569 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { 1614 uint32 ApplyCwndFieldTrialPolicy(int cwnd) {
1570 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); 1615 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd");
1571 if (!trial) { 1616 if (!trial) {
1572 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; 1617 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList";
1573 return cwnd; 1618 return cwnd;
1574 } 1619 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 1685
1641 void SpdySession::SendSettings(const SettingsMap& settings) { 1686 void SpdySession::SendSettings(const SettingsMap& settings) {
1642 net_log_.AddEvent( 1687 net_log_.AddEvent(
1643 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, 1688 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS,
1644 base::Bind(&NetLogSpdySettingsCallback, &settings)); 1689 base::Bind(&NetLogSpdySettingsCallback, &settings));
1645 1690
1646 // Create the SETTINGS frame and send it. 1691 // Create the SETTINGS frame and send it.
1647 DCHECK(buffered_spdy_framer_.get()); 1692 DCHECK(buffered_spdy_framer_.get());
1648 scoped_ptr<SpdySettingsControlFrame> settings_frame( 1693 scoped_ptr<SpdySettingsControlFrame> settings_frame(
1649 buffered_spdy_framer_->CreateSettings(settings)); 1694 buffered_spdy_framer_->CreateSettings(settings));
1650 QueueFrame(settings_frame.get(), HIGHEST, NULL); 1695 sent_settings_ = true;
1696 QueueFrame(settings_frame.release(), HIGHEST);
1651 } 1697 }
1652 1698
1653 void SpdySession::HandleSetting(uint32 id, uint32 value) { 1699 void SpdySession::HandleSetting(uint32 id, uint32 value) {
1654 switch (id) { 1700 switch (id) {
1655 case SETTINGS_MAX_CONCURRENT_STREAMS: 1701 case SETTINGS_MAX_CONCURRENT_STREAMS:
1656 max_concurrent_streams_ = std::min(static_cast<size_t>(value), 1702 max_concurrent_streams_ = std::min(static_cast<size_t>(value),
1657 g_max_concurrent_stream_limit); 1703 g_max_concurrent_stream_limit);
1658 ProcessPendingCreateStreams(); 1704 ProcessPendingCreateStreams();
1659 break; 1705 break;
1660 case SETTINGS_INITIAL_WINDOW_SIZE: 1706 case SETTINGS_INITIAL_WINDOW_SIZE:
(...skipping 14 matching lines...) Expand all
1675 } 1721 }
1676 } 1722 }
1677 1723
1678 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { 1724 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) {
1679 ActiveStreamMap::iterator it; 1725 ActiveStreamMap::iterator it;
1680 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) { 1726 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) {
1681 const scoped_refptr<SpdyStream>& stream = it->second; 1727 const scoped_refptr<SpdyStream>& stream = it->second;
1682 DCHECK(stream); 1728 DCHECK(stream);
1683 stream->AdjustSendWindowSize(delta_window_size); 1729 stream->AdjustSendWindowSize(delta_window_size);
1684 } 1730 }
1731
1732 CreatedStreamSet::iterator i;
1733 for (i = created_streams_.begin(); i != created_streams_.end(); i++) {
1734 const scoped_refptr<SpdyStream>& stream = *i;
1735 stream->AdjustSendWindowSize(delta_window_size);
1736 }
1685 } 1737 }
1686 1738
1687 void SpdySession::SendPrefacePingIfNoneInFlight() { 1739 void SpdySession::SendPrefacePingIfNoneInFlight() {
1688 if (pings_in_flight_ || !g_enable_ping_based_connection_checking) 1740 if (pings_in_flight_ || !g_enable_ping_based_connection_checking)
1689 return; 1741 return;
1690 1742
1691 base::TimeTicks now = base::TimeTicks::Now(); 1743 base::TimeTicks now = base::TimeTicks::Now();
1692 // If there is no activity in the session, then send a preface-PING. 1744 // If there is no activity in the session, then send a preface-PING.
1693 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) 1745 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_)
1694 SendPrefacePing(); 1746 SendPrefacePing();
1695 } 1747 }
1696 1748
1697 void SpdySession::SendPrefacePing() { 1749 void SpdySession::SendPrefacePing() {
1698 WritePingFrame(next_ping_id_); 1750 WritePingFrame(next_ping_id_);
1699 } 1751 }
1700 1752
1701 void SpdySession::WritePingFrame(uint32 unique_id) { 1753 void SpdySession::WritePingFrame(uint32 unique_id) {
1702 DCHECK(buffered_spdy_framer_.get()); 1754 DCHECK(buffered_spdy_framer_.get());
1703 scoped_ptr<SpdyPingControlFrame> ping_frame( 1755 scoped_ptr<SpdyPingControlFrame> ping_frame(
1704 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); 1756 buffered_spdy_framer_->CreatePingFrame(next_ping_id_));
1705 QueueFrame(ping_frame.get(), HIGHEST, NULL); 1757 QueueFrame(ping_frame.release(), HIGHEST);
1706 1758
1707 if (net_log().IsLoggingAllEvents()) { 1759 if (net_log().IsLoggingAllEvents()) {
1708 net_log().AddEvent( 1760 net_log().AddEvent(
1709 NetLog::TYPE_SPDY_SESSION_PING, 1761 NetLog::TYPE_SPDY_SESSION_PING,
1710 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent")); 1762 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent"));
1711 } 1763 }
1712 if (unique_id % 2 != 0) { 1764 if (unique_id % 2 != 0) {
1713 next_ping_id_ += 2; 1765 next_ping_id_ += 2;
1714 ++pings_in_flight_; 1766 ++pings_in_flight_;
1715 PlanToCheckPingStatus(); 1767 PlanToCheckPingStatus();
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 SSLClientSocket* SpdySession::GetSSLClientSocket() const { 1910 SSLClientSocket* SpdySession::GetSSLClientSocket() const {
1859 if (!is_secure_) 1911 if (!is_secure_)
1860 return NULL; 1912 return NULL;
1861 SSLClientSocket* ssl_socket = 1913 SSLClientSocket* ssl_socket =
1862 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 1914 reinterpret_cast<SSLClientSocket*>(connection_->socket());
1863 DCHECK(ssl_socket); 1915 DCHECK(ssl_socket);
1864 return ssl_socket; 1916 return ssl_socket;
1865 } 1917 }
1866 1918
1867 } // namespace net 1919 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698