Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #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 Loading... | |
| 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 Loading... | |
| 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) { | |
| 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 Loading... | |
| 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); |
|
ramant (doing other things)
2012/06/26 23:30:25
nit: "When expressions are wrapped, the operator s
Ryan Hamilton
2012/06/27 16:58:28
Done.
| |
| 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 } |
| 407 | 437 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 if (uncompressed_control_frame->type() == SYN_STREAM) { | |
| 924 int uncompressed_size = uncompressed_control_frame->length(); | |
| 925 int compressed_size = compressed_frame->length(); | |
| 926 // Make sure we avoid early decimal truncation. | |
| 927 int compression_pct = 100 - (100* compressed_size)/uncompressed_size; | |
| 928 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage", | |
| 929 compression_pct); | |
| 930 } | |
| 931 | |
| 932 // TODO(mbelshe): We have too much copying of data here. | |
| 933 IOBufferWithSize* buffer = new IOBufferWithSize(size); | |
| 934 memcpy(buffer->data(), compressed_frame->data(), size); | |
| 935 | |
| 936 // Attempt to send the frame. | |
| 937 in_flight_write_ = SpdyIOBuffer(buffer, size, HIGHEST, | |
| 938 next_buffer.stream()); | |
| 939 } else { | |
| 940 size = uncompressed_frame.length() + SpdyFrame::kHeaderSize; | |
| 941 in_flight_write_ = next_buffer; | |
| 942 } | |
| 943 } else { | 930 } else { |
| 944 DCHECK(in_flight_write_.buffer()->BytesRemaining()); | 931 DCHECK(in_flight_write_.buffer()->BytesRemaining()); |
| 945 } | 932 } |
| 946 | 933 |
| 947 write_pending_ = true; | 934 write_pending_ = true; |
| 948 int rv = connection_->socket()->Write( | 935 int rv = connection_->socket()->Write( |
| 949 in_flight_write_.buffer(), | 936 in_flight_write_.buffer(), |
| 950 in_flight_write_.buffer()->BytesRemaining(), | 937 in_flight_write_.buffer()->BytesRemaining(), |
| 951 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this))); | 938 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this))); |
| 952 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 Loading... | |
| 986 while (!active_streams_.empty()) { | 973 while (!active_streams_.empty()) { |
| 987 ActiveStreamMap::iterator it = active_streams_.begin(); | 974 ActiveStreamMap::iterator it = active_streams_.begin(); |
| 988 const scoped_refptr<SpdyStream>& stream = it->second; | 975 const scoped_refptr<SpdyStream>& stream = it->second; |
| 989 DCHECK(stream); | 976 DCHECK(stream); |
| 990 std::string description = base::StringPrintf( | 977 std::string description = base::StringPrintf( |
| 991 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); | 978 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); |
| 992 stream->LogStreamError(status, description); | 979 stream->LogStreamError(status, description); |
| 993 DeleteStream(stream->stream_id(), status); | 980 DeleteStream(stream->stream_id(), status); |
| 994 } | 981 } |
| 995 | 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); | |
|
ramant (doing other things)
2012/06/26 23:30:25
nit: consider sharing of code between lines 976-97
Ryan Hamilton
2012/06/27 16:58:28
Done.
| |
| 990 created_streams_.erase(it); | |
| 991 } | |
| 992 | |
| 996 // We also need to drain the queue. | 993 // We also need to drain the queue. |
| 997 while (queue_.size()) | 994 while (!write_queue_.empty()) { |
| 998 queue_.pop(); | 995 SpdyIOBufferProducer* producer = write_queue_.top(); |
| 996 stream_producers_.erase(producer); | |
| 997 delete producer; | |
| 998 write_queue_.pop(); | |
| 999 } | |
| 999 } | 1000 } |
| 1000 | 1001 |
| 1001 int SpdySession::GetNewStreamId() { | 1002 int SpdySession::GetNewStreamId() { |
| 1002 int id = stream_hi_water_mark_; | 1003 int id = stream_hi_water_mark_; |
| 1003 stream_hi_water_mark_ += 2; | 1004 stream_hi_water_mark_ += 2; |
| 1004 if (stream_hi_water_mark_ > 0x7fff) | 1005 if (stream_hi_water_mark_ > 0x7fff) |
| 1005 stream_hi_water_mark_ = 1; | 1006 stream_hi_water_mark_ = 1; |
| 1006 return id; | 1007 return id; |
| 1007 } | 1008 } |
| 1008 | 1009 |
| 1009 void SpdySession::QueueFrame(SpdyFrame* frame, | |
| 1010 RequestPriority priority, | |
| 1011 SpdyStream* stream) { | |
| 1012 int length = SpdyFrame::kHeaderSize + frame->length(); | |
| 1013 IOBuffer* buffer = new IOBuffer(length); | |
| 1014 memcpy(buffer->data(), frame->data(), length); | |
| 1015 queue_.push(SpdyIOBuffer(buffer, length, priority, stream)); | |
| 1016 | |
| 1017 WriteSocketLater(); | |
| 1018 } | |
| 1019 | |
| 1020 void SpdySession::CloseSessionOnError(net::Error err, | 1010 void SpdySession::CloseSessionOnError(net::Error err, |
| 1021 bool remove_from_pool, | 1011 bool remove_from_pool, |
| 1022 const std::string& description) { | 1012 const std::string& description) { |
| 1023 // 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 |
| 1024 // to |this|. Hold a reference through this function. | 1014 // to |this|. Hold a reference through this function. |
| 1025 scoped_refptr<SpdySession> self(this); | 1015 scoped_refptr<SpdySession> self(this); |
| 1026 | 1016 |
| 1027 DCHECK_LT(err, OK); | 1017 DCHECK_LT(err, OK); |
| 1028 net_log_.AddEvent( | 1018 net_log_.AddEvent( |
| 1029 NetLog::TYPE_SPDY_SESSION_CLOSE, | 1019 NetLog::TYPE_SPDY_SESSION_CLOSE, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1099 return connection_->socket()->GetPeerAddress(address); | 1089 return connection_->socket()->GetPeerAddress(address); |
| 1100 } | 1090 } |
| 1101 | 1091 |
| 1102 int SpdySession::GetLocalAddress(IPEndPoint* address) const { | 1092 int SpdySession::GetLocalAddress(IPEndPoint* address) const { |
| 1103 if (!connection_->socket()) | 1093 if (!connection_->socket()) |
| 1104 return ERR_SOCKET_NOT_CONNECTED; | 1094 return ERR_SOCKET_NOT_CONNECTED; |
| 1105 | 1095 |
| 1106 return connection_->socket()->GetLocalAddress(address); | 1096 return connection_->socket()->GetLocalAddress(address); |
| 1107 } | 1097 } |
| 1108 | 1098 |
| 1099 class SimpleSpdyIOBufferProducer : public SpdySession::SpdyIOBufferProducer { | |
| 1100 public: | |
| 1101 SimpleSpdyIOBufferProducer(SpdyFrame* frame, | |
| 1102 RequestPriority priority) | |
| 1103 : frame_(frame), | |
|
ramant (doing other things)
2012/06/26 23:30:25
nit: indent "RequestPriority ..."
Ryan Hamilton
2012/06/27 16:58:28
Done.
| |
| 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); | |
|
ramant (doing other things)
2012/06/26 23:30:25
nit: " = " should be in the previous line.
Ryan Hamilton
2012/06/27 16:58:28
Done.
Ryan Hamilton
2012/06/27 16:58:28
Done.
| |
| 1126 WriteSocketLater(); | |
| 1127 } | |
| 1128 | |
| 1109 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 } | |
| 1110 const SpdyStreamId id = stream->stream_id(); | 1134 const SpdyStreamId id = stream->stream_id(); |
| 1111 DCHECK(!IsStreamActive(id)); | 1135 DCHECK(!IsStreamActive(id)); |
| 1112 | 1136 |
| 1113 active_streams_[id] = stream; | 1137 active_streams_[id] = stream; |
| 1114 } | 1138 } |
| 1115 | 1139 |
| 1116 void SpdySession::DeleteStream(SpdyStreamId id, int status) { | 1140 void SpdySession::DeleteStream(SpdyStreamId id, int status) { |
| 1117 // For push streams, if they are being deleted normally, we leave | 1141 // For push streams, if they are being deleted normally, we leave |
| 1118 // the stream in the unclaimed_pushed_streams_ list. However, if | 1142 // the stream in the unclaimed_pushed_streams_ list. However, if |
| 1119 // the stream is errored out, clean it up entirely. | 1143 // the stream is errored out, clean it up entirely. |
| 1120 if (status != OK) { | 1144 if (status != OK) { |
| 1121 PushedStreamMap::iterator it; | 1145 PushedStreamMap::iterator it; |
| 1122 for (it = unclaimed_pushed_streams_.begin(); | 1146 for (it = unclaimed_pushed_streams_.begin(); |
| 1123 it != unclaimed_pushed_streams_.end(); ++it) { | 1147 it != unclaimed_pushed_streams_.end(); ++it) { |
| 1124 scoped_refptr<SpdyStream> curr = it->second; | 1148 scoped_refptr<SpdyStream> curr = it->second; |
| 1125 if (id == curr->stream_id()) { | 1149 if (id == curr->stream_id()) { |
| 1126 unclaimed_pushed_streams_.erase(it); | 1150 unclaimed_pushed_streams_.erase(it); |
| 1127 break; | 1151 break; |
| 1128 } | 1152 } |
| 1129 } | 1153 } |
| 1130 } | 1154 } |
| 1131 | 1155 |
| 1132 // The stream might have been deleted. | 1156 // The stream might have been deleted. |
| 1133 ActiveStreamMap::iterator it2 = active_streams_.find(id); | 1157 ActiveStreamMap::iterator it2 = active_streams_.find(id); |
| 1134 if (it2 == active_streams_.end()) | 1158 if (it2 == active_streams_.end()) |
| 1135 return; | 1159 return; |
| 1136 | 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 | |
| 1137 // If this is an active stream, call the callback. | 1174 // If this is an active stream, call the callback. |
| 1138 const scoped_refptr<SpdyStream> stream(it2->second); | 1175 const scoped_refptr<SpdyStream> stream(it2->second); |
| 1139 active_streams_.erase(it2); | 1176 active_streams_.erase(it2); |
| 1140 if (stream) | 1177 if (stream) |
| 1141 stream->OnClose(status); | 1178 stream->OnClose(status); |
| 1142 ProcessPendingCreateStreams(); | 1179 ProcessPendingCreateStreams(); |
| 1143 } | 1180 } |
| 1144 | 1181 |
| 1145 void SpdySession::RemoveFromPool() { | 1182 void SpdySession::RemoveFromPool() { |
| 1146 if (spdy_session_pool_) { | 1183 if (spdy_session_pool_) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1242 value); | 1279 value); |
| 1243 received_settings_ = true; | 1280 received_settings_ = true; |
| 1244 | 1281 |
| 1245 // Log the setting. | 1282 // Log the setting. |
| 1246 net_log_.AddEvent( | 1283 net_log_.AddEvent( |
| 1247 NetLog::TYPE_SPDY_SESSION_RECV_SETTING, | 1284 NetLog::TYPE_SPDY_SESSION_RECV_SETTING, |
| 1248 base::Bind(&NetLogSpdySettingCallback, | 1285 base::Bind(&NetLogSpdySettingCallback, |
| 1249 id, static_cast<SpdySettingsFlags>(flags), value)); | 1286 id, static_cast<SpdySettingsFlags>(flags), value)); |
| 1250 } | 1287 } |
| 1251 | 1288 |
| 1289 void SpdySession::OnControlFrameCompressed( | |
| 1290 const SpdyControlFrame& uncompressed_frame, | |
| 1291 const SpdyControlFrame& compressed_frame) { | |
| 1292 if (uncompressed_frame.type() == SYN_STREAM) { | |
| 1293 int uncompressed_size = uncompressed_frame.length(); | |
| 1294 int compressed_size = compressed_frame.length(); | |
| 1295 // Make sure we avoid early decimal truncation. | |
| 1296 int compression_pct = 100 - (100* compressed_size)/uncompressed_size; | |
| 1297 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage", | |
| 1298 compression_pct); | |
| 1299 } | |
| 1300 } | |
| 1301 | |
| 1302 | |
| 1252 bool SpdySession::Respond(const SpdyHeaderBlock& headers, | 1303 bool SpdySession::Respond(const SpdyHeaderBlock& headers, |
| 1253 const scoped_refptr<SpdyStream> stream) { | 1304 const scoped_refptr<SpdyStream> stream) { |
| 1254 int rv = OK; | 1305 int rv = OK; |
| 1255 rv = stream->OnResponseReceived(headers); | 1306 rv = stream->OnResponseReceived(headers); |
| 1256 if (rv < 0) { | 1307 if (rv < 0) { |
| 1257 DCHECK_NE(rv, ERR_IO_PENDING); | 1308 DCHECK_NE(rv, ERR_IO_PENDING); |
| 1258 const SpdyStreamId stream_id = stream->stream_id(); | 1309 const SpdyStreamId stream_id = stream->stream_id(); |
| 1259 DeleteStream(stream_id, rv); | 1310 DeleteStream(stream_id, rv); |
| 1260 return false; | 1311 return false; |
| 1261 } | 1312 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1342 } | 1393 } |
| 1343 | 1394 |
| 1344 // 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. |
| 1345 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url); | 1396 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url); |
| 1346 if (it != unclaimed_pushed_streams_.end()) { | 1397 if (it != unclaimed_pushed_streams_.end()) { |
| 1347 ResetStream(stream_id, PROTOCOL_ERROR, | 1398 ResetStream(stream_id, PROTOCOL_ERROR, |
| 1348 "Received duplicate pushed stream with url: " + url); | 1399 "Received duplicate pushed stream with url: " + url); |
| 1349 return; | 1400 return; |
| 1350 } | 1401 } |
| 1351 | 1402 |
| 1352 scoped_refptr<SpdyStream> stream( | 1403 scoped_refptr<SpdyStream> stream(new SpdyStream(this, true, net_log_)); |
| 1353 new SpdyStream(this, stream_id, true, net_log_)); | 1404 stream->set_stream_id(stream_id); |
| 1354 | 1405 |
| 1355 stream->set_path(gurl.PathForRequest()); | 1406 stream->set_path(gurl.PathForRequest()); |
| 1356 stream->set_send_window_size(initial_send_window_size_); | 1407 stream->set_send_window_size(initial_send_window_size_); |
| 1357 stream->set_recv_window_size(initial_recv_window_size_); | 1408 stream->set_recv_window_size(initial_recv_window_size_); |
| 1358 | 1409 |
| 1359 unclaimed_pushed_streams_[url] = stream; | 1410 unclaimed_pushed_streams_[url] = stream; |
| 1360 | 1411 |
| 1361 ActivateStream(stream); | 1412 ActivateStream(stream); |
| 1362 stream->set_response_received(); | 1413 stream->set_response_received(); |
| 1363 | 1414 |
| 1364 // Parse the headers. | 1415 // Parse the headers. |
| 1365 if (!Respond(*headers, stream)) | 1416 if (!Respond(*headers, stream)) |
| 1366 return; | 1417 return; |
| 1367 | 1418 |
| 1368 base::StatsCounter push_requests("spdy.pushed_streams"); | 1419 base::StatsCounter push_requests("spdy.pushed_streams"); |
| 1369 push_requests.Increment(); | 1420 push_requests.Increment(); |
| 1370 } | 1421 } |
| 1371 | 1422 |
| 1372 void SpdySession::OnSynReply(const SpdySynReplyControlFrame& frame, | 1423 void SpdySession::OnSynReply(const SpdySynReplyControlFrame& frame, |
| 1373 const linked_ptr<SpdyHeaderBlock>& headers) { | 1424 const linked_ptr<SpdyHeaderBlock>& headers) { |
| 1374 SpdyStreamId stream_id = frame.stream_id(); | 1425 SpdyStreamId stream_id = frame.stream_id(); |
| 1375 | |
| 1376 if (net_log().IsLoggingAllEvents()) { | 1426 if (net_log().IsLoggingAllEvents()) { |
| 1377 net_log().AddEvent( | 1427 net_log().AddEvent( |
| 1378 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, | 1428 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, |
| 1379 base::Bind(&NetLogSpdySynCallback, | 1429 base::Bind(&NetLogSpdySynCallback, |
| 1380 headers.get(), static_cast<SpdyControlFlags>(frame.flags()), | 1430 headers.get(), static_cast<SpdyControlFlags>(frame.flags()), |
| 1381 stream_id, 0)); | 1431 stream_id, 0)); |
| 1382 } | 1432 } |
| 1383 | 1433 |
| 1384 if (!IsStreamActive(stream_id)) { | 1434 if (!IsStreamActive(stream_id)) { |
| 1385 // 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 Loading... | |
| 1549 CHECK_EQ(stream->stream_id(), stream_id); | 1599 CHECK_EQ(stream->stream_id(), stream_id); |
| 1550 | 1600 |
| 1551 net_log_.AddEvent( | 1601 net_log_.AddEvent( |
| 1552 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE, | 1602 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE, |
| 1553 base::Bind(&NetLogSpdyWindowUpdateCallback, | 1603 base::Bind(&NetLogSpdyWindowUpdateCallback, |
| 1554 stream_id, delta_window_size)); | 1604 stream_id, delta_window_size)); |
| 1555 | 1605 |
| 1556 DCHECK(buffered_spdy_framer_.get()); | 1606 DCHECK(buffered_spdy_framer_.get()); |
| 1557 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame( | 1607 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame( |
| 1558 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); | 1608 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); |
| 1559 QueueFrame(window_update_frame.get(), stream->priority(), NULL); | 1609 QueueFrame(window_update_frame.release(), stream->priority()); |
| 1560 } | 1610 } |
| 1561 | 1611 |
| 1562 // 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 |
| 1563 // field trial policy. | 1613 // field trial policy. |
| 1564 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { | 1614 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { |
| 1565 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); | 1615 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); |
| 1566 if (!trial) { | 1616 if (!trial) { |
| 1567 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; | 1617 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; |
| 1568 return cwnd; | 1618 return cwnd; |
| 1569 } | 1619 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1589 // Create a new settings frame notifying the sever of our | 1639 // Create a new settings frame notifying the sever of our |
| 1590 // max_concurrent_streams_ and initial window size. | 1640 // max_concurrent_streams_ and initial window size. |
| 1591 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = | 1641 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = |
| 1592 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialMaxConcurrentStreams); | 1642 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialMaxConcurrentStreams); |
| 1593 if (GetProtocolVersion() > 2 && | 1643 if (GetProtocolVersion() > 2 && |
| 1594 initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { | 1644 initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { |
| 1595 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = | 1645 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = |
| 1596 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_recv_window_size_); | 1646 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_recv_window_size_); |
| 1597 } | 1647 } |
| 1598 sent_settings_ = true; | 1648 sent_settings_ = true; |
| 1599 SendSettings(settings_map); | 1649 SendSettings(settings_map); |
|
ramant (doing other things)
2012/06/26 23:30:25
nit: delete "sent_settings_ = true;"?
Ryan Hamilton
2012/06/27 16:58:28
Done.
| |
| 1600 } | 1650 } |
| 1601 | 1651 |
| 1602 // Next notify the server about the settings they have previously | 1652 // Next notify the server about the settings they have previously |
| 1603 // told us to use when communicating with them. | 1653 // told us to use when communicating with them. |
| 1604 const SettingsMap& settings_map = | 1654 const SettingsMap& settings_map = |
| 1605 http_server_properties_->GetSpdySettings(host_port_pair()); | 1655 http_server_properties_->GetSpdySettings(host_port_pair()); |
| 1606 if (settings_map.empty()) | 1656 if (settings_map.empty()) |
| 1607 return; | 1657 return; |
| 1608 | 1658 |
| 1609 // Record Histogram Data and Apply the SpdyCwnd FieldTrial if applicable. | 1659 // Record Histogram Data and Apply the SpdyCwnd FieldTrial if applicable. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1622 const SettingsMap& settings_map_new = | 1672 const SettingsMap& settings_map_new = |
| 1623 http_server_properties_->GetSpdySettings(host_port_pair()); | 1673 http_server_properties_->GetSpdySettings(host_port_pair()); |
| 1624 for (SettingsMap::const_iterator i = settings_map_new.begin(), | 1674 for (SettingsMap::const_iterator i = settings_map_new.begin(), |
| 1625 end = settings_map_new.end(); i != end; ++i) { | 1675 end = settings_map_new.end(); i != end; ++i) { |
| 1626 const SpdySettingsIds new_id = i->first; | 1676 const SpdySettingsIds new_id = i->first; |
| 1627 const uint32 new_val = i->second.second; | 1677 const uint32 new_val = i->second.second; |
| 1628 HandleSetting(new_id, new_val); | 1678 HandleSetting(new_id, new_val); |
| 1629 } | 1679 } |
| 1630 | 1680 |
| 1631 sent_settings_ = true; | 1681 sent_settings_ = true; |
| 1632 SendSettings(settings_map_new); | 1682 SendSettings(settings_map_new); |
|
ramant (doing other things)
2012/06/26 23:30:25
nit: delete "sent_settings_ = true;"?
Ryan Hamilton
2012/06/27 16:58:28
Done.
| |
| 1633 } | 1683 } |
| 1634 | 1684 |
| 1635 | 1685 |
| 1636 void SpdySession::SendSettings(const SettingsMap& settings) { | 1686 void SpdySession::SendSettings(const SettingsMap& settings) { |
| 1637 net_log_.AddEvent( | 1687 net_log_.AddEvent( |
| 1638 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, | 1688 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, |
| 1639 base::Bind(&NetLogSpdySettingsCallback, &settings)); | 1689 base::Bind(&NetLogSpdySettingsCallback, &settings)); |
| 1640 | 1690 |
| 1641 // Create the SETTINGS frame and send it. | 1691 // Create the SETTINGS frame and send it. |
| 1642 DCHECK(buffered_spdy_framer_.get()); | 1692 DCHECK(buffered_spdy_framer_.get()); |
| 1643 scoped_ptr<SpdySettingsControlFrame> settings_frame( | 1693 scoped_ptr<SpdySettingsControlFrame> settings_frame( |
| 1644 buffered_spdy_framer_->CreateSettings(settings)); | 1694 buffered_spdy_framer_->CreateSettings(settings)); |
| 1645 QueueFrame(settings_frame.get(), HIGHEST, NULL); | 1695 sent_settings_ = true; |
| 1696 QueueFrame(settings_frame.release(), HIGHEST); | |
| 1646 } | 1697 } |
| 1647 | 1698 |
| 1648 void SpdySession::HandleSetting(uint32 id, uint32 value) { | 1699 void SpdySession::HandleSetting(uint32 id, uint32 value) { |
| 1649 switch (id) { | 1700 switch (id) { |
| 1650 case SETTINGS_MAX_CONCURRENT_STREAMS: | 1701 case SETTINGS_MAX_CONCURRENT_STREAMS: |
| 1651 max_concurrent_streams_ = std::min(static_cast<size_t>(value), | 1702 max_concurrent_streams_ = std::min(static_cast<size_t>(value), |
| 1652 g_max_concurrent_stream_limit); | 1703 g_max_concurrent_stream_limit); |
| 1653 ProcessPendingCreateStreams(); | 1704 ProcessPendingCreateStreams(); |
| 1654 break; | 1705 break; |
| 1655 case SETTINGS_INITIAL_WINDOW_SIZE: | 1706 case SETTINGS_INITIAL_WINDOW_SIZE: |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1670 } | 1721 } |
| 1671 } | 1722 } |
| 1672 | 1723 |
| 1673 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { | 1724 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { |
| 1674 ActiveStreamMap::iterator it; | 1725 ActiveStreamMap::iterator it; |
| 1675 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) { | 1726 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) { |
| 1676 const scoped_refptr<SpdyStream>& stream = it->second; | 1727 const scoped_refptr<SpdyStream>& stream = it->second; |
| 1677 DCHECK(stream); | 1728 DCHECK(stream); |
| 1678 stream->AdjustSendWindowSize(delta_window_size); | 1729 stream->AdjustSendWindowSize(delta_window_size); |
| 1679 } | 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 } | |
| 1680 } | 1737 } |
| 1681 | 1738 |
| 1682 void SpdySession::SendPrefacePingIfNoneInFlight() { | 1739 void SpdySession::SendPrefacePingIfNoneInFlight() { |
| 1683 if (pings_in_flight_ || !g_enable_ping_based_connection_checking) | 1740 if (pings_in_flight_ || !g_enable_ping_based_connection_checking) |
| 1684 return; | 1741 return; |
| 1685 | 1742 |
| 1686 base::TimeTicks now = base::TimeTicks::Now(); | 1743 base::TimeTicks now = base::TimeTicks::Now(); |
| 1687 // 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. |
| 1688 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) | 1745 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) |
| 1689 SendPrefacePing(); | 1746 SendPrefacePing(); |
| 1690 } | 1747 } |
| 1691 | 1748 |
| 1692 void SpdySession::SendPrefacePing() { | 1749 void SpdySession::SendPrefacePing() { |
| 1693 WritePingFrame(next_ping_id_); | 1750 WritePingFrame(next_ping_id_); |
| 1694 } | 1751 } |
| 1695 | 1752 |
| 1696 void SpdySession::WritePingFrame(uint32 unique_id) { | 1753 void SpdySession::WritePingFrame(uint32 unique_id) { |
| 1697 DCHECK(buffered_spdy_framer_.get()); | 1754 DCHECK(buffered_spdy_framer_.get()); |
| 1698 scoped_ptr<SpdyPingControlFrame> ping_frame( | 1755 scoped_ptr<SpdyPingControlFrame> ping_frame( |
| 1699 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); | 1756 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); |
| 1700 QueueFrame(ping_frame.get(), HIGHEST, NULL); | 1757 QueueFrame(ping_frame.release(), HIGHEST); |
| 1701 | 1758 |
| 1702 if (net_log().IsLoggingAllEvents()) { | 1759 if (net_log().IsLoggingAllEvents()) { |
| 1703 net_log().AddEvent( | 1760 net_log().AddEvent( |
| 1704 NetLog::TYPE_SPDY_SESSION_PING, | 1761 NetLog::TYPE_SPDY_SESSION_PING, |
| 1705 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent")); | 1762 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent")); |
| 1706 } | 1763 } |
| 1707 if (unique_id % 2 != 0) { | 1764 if (unique_id % 2 != 0) { |
| 1708 next_ping_id_ += 2; | 1765 next_ping_id_ += 2; |
| 1709 ++pings_in_flight_; | 1766 ++pings_in_flight_; |
| 1710 PlanToCheckPingStatus(); | 1767 PlanToCheckPingStatus(); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1853 SSLClientSocket* SpdySession::GetSSLClientSocket() const { | 1910 SSLClientSocket* SpdySession::GetSSLClientSocket() const { |
| 1854 if (!is_secure_) | 1911 if (!is_secure_) |
| 1855 return NULL; | 1912 return NULL; |
| 1856 SSLClientSocket* ssl_socket = | 1913 SSLClientSocket* ssl_socket = |
| 1857 reinterpret_cast<SSLClientSocket*>(connection_->socket()); | 1914 reinterpret_cast<SSLClientSocket*>(connection_->socket()); |
| 1858 DCHECK(ssl_socket); | 1915 DCHECK(ssl_socket); |
| 1859 return ssl_socket; | 1916 return ssl_socket; |
| 1860 } | 1917 } |
| 1861 | 1918 |
| 1862 } // namespace net | 1919 } // namespace net |
| OLD | NEW |