| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/linked_ptr.h" | 8 #include "base/linked_ptr.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 } | 271 } |
| 272 | 272 |
| 273 const std::string& path = url.PathForRequest(); | 273 const std::string& path = url.PathForRequest(); |
| 274 | 274 |
| 275 *stream = GetActivePushStream(path); | 275 *stream = GetActivePushStream(path); |
| 276 if (stream->get()) { | 276 if (stream->get()) { |
| 277 DCHECK(streams_pushed_and_claimed_count_ < streams_pushed_count_); | 277 DCHECK(streams_pushed_and_claimed_count_ < streams_pushed_count_); |
| 278 streams_pushed_and_claimed_count_++; | 278 streams_pushed_and_claimed_count_++; |
| 279 return OK; | 279 return OK; |
| 280 } | 280 } |
| 281 | 281 return NULL; |
| 282 // Check if we have a pending push stream for this url. | |
| 283 // Note that we shouldn't have a pushed stream for non-GET method. | |
| 284 PendingStreamMap::iterator it; | |
| 285 it = pending_streams_.find(path); | |
| 286 if (it != pending_streams_.end()) { | |
| 287 // Server has advertised a stream, but not yet sent it. | |
| 288 DCHECK(!it->second); | |
| 289 // Server will assign a stream id when the push stream arrives. Use 0 for | |
| 290 // now. | |
| 291 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM, NULL); | |
| 292 *stream = new SpdyStream(this, 0, true); | |
| 293 (*stream)->set_path(path); | |
| 294 (*stream)->set_net_log(stream_net_log); | |
| 295 it->second = *stream; | |
| 296 return OK; | |
| 297 } | |
| 298 return OK; | |
| 299 } | 282 } |
| 300 | 283 |
| 301 int SpdySession::CreateStream( | 284 int SpdySession::CreateStream( |
| 302 const GURL& url, | 285 const GURL& url, |
| 303 RequestPriority priority, | 286 RequestPriority priority, |
| 304 scoped_refptr<SpdyStream>* spdy_stream, | 287 scoped_refptr<SpdyStream>* spdy_stream, |
| 305 const BoundNetLog& stream_net_log, | 288 const BoundNetLog& stream_net_log, |
| 306 CompletionCallback* callback) { | 289 CompletionCallback* callback) { |
| 307 if (!max_concurrent_streams_ || | 290 if (!max_concurrent_streams_ || |
| 308 active_streams_.size() < max_concurrent_streams_) { | 291 active_streams_.size() < max_concurrent_streams_) { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { | 448 void SpdySession::CloseStream(spdy::SpdyStreamId stream_id, int status) { |
| 466 LOG(INFO) << "Closing stream " << stream_id << " with status " << status; | 449 LOG(INFO) << "Closing stream " << stream_id << " with status " << status; |
| 467 // TODO(mbelshe): We should send a RST_STREAM control frame here | 450 // TODO(mbelshe): We should send a RST_STREAM control frame here |
| 468 // so that the server can cancel a large send. | 451 // so that the server can cancel a large send. |
| 469 | 452 |
| 470 DeleteStream(stream_id, status); | 453 DeleteStream(stream_id, status); |
| 471 } | 454 } |
| 472 | 455 |
| 473 void SpdySession::ResetStream( | 456 void SpdySession::ResetStream( |
| 474 spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status) { | 457 spdy::SpdyStreamId stream_id, spdy::SpdyStatusCodes status) { |
| 475 DCHECK(IsStreamActive(stream_id)); | |
| 476 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | |
| 477 CHECK_EQ(stream->stream_id(), stream_id); | |
| 478 | |
| 479 LOG(INFO) << "Sending a RST_STREAM frame for stream " << stream_id | 458 LOG(INFO) << "Sending a RST_STREAM frame for stream " << stream_id |
| 480 << " with status " << status; | 459 << " with status " << status; |
| 481 | 460 |
| 482 scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame( | 461 scoped_ptr<spdy::SpdyRstStreamControlFrame> rst_frame( |
| 483 spdy_framer_.CreateRstStream(stream_id, status)); | 462 spdy_framer_.CreateRstStream(stream_id, status)); |
| 484 QueueFrame(rst_frame.get(), stream->priority(), stream); | 463 |
| 464 // Default to lowest priority unless we know otherwise. |
| 465 int priority = 3; |
| 466 if(IsStreamActive(stream_id)) { |
| 467 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 468 priority = stream->priority(); |
| 469 } |
| 470 QueueFrame(rst_frame.get(), priority, NULL); |
| 485 | 471 |
| 486 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); | 472 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); |
| 487 } | 473 } |
| 488 | 474 |
| 489 bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const { | 475 bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const { |
| 490 return ContainsKey(active_streams_, stream_id); | 476 return ContainsKey(active_streams_, stream_id); |
| 491 } | 477 } |
| 492 | 478 |
| 493 LoadState SpdySession::GetLoadState() const { | 479 LoadState SpdySession::GetLoadState() const { |
| 494 // NOTE: The application only queries the LoadState via the | 480 // NOTE: The application only queries the LoadState via the |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 } | 764 } |
| 779 | 765 |
| 780 void SpdySession::CloseAllStreams(net::Error status) { | 766 void SpdySession::CloseAllStreams(net::Error status) { |
| 781 LOG(INFO) << "Closing all SPDY Streams for " << host_port_pair().ToString(); | 767 LOG(INFO) << "Closing all SPDY Streams for " << host_port_pair().ToString(); |
| 782 | 768 |
| 783 static StatsCounter abandoned_streams("spdy.abandoned_streams"); | 769 static StatsCounter abandoned_streams("spdy.abandoned_streams"); |
| 784 static StatsCounter abandoned_push_streams("spdy.abandoned_push_streams"); | 770 static StatsCounter abandoned_push_streams("spdy.abandoned_push_streams"); |
| 785 | 771 |
| 786 if (!active_streams_.empty()) | 772 if (!active_streams_.empty()) |
| 787 abandoned_streams.Add(active_streams_.size()); | 773 abandoned_streams.Add(active_streams_.size()); |
| 788 if (!pushed_streams_.empty()) { | 774 if (!unclaimed_pushed_streams_.empty()) { |
| 789 streams_abandoned_count_ += pushed_streams_.size(); | 775 streams_abandoned_count_ += unclaimed_pushed_streams_.size(); |
| 790 abandoned_push_streams.Add(pushed_streams_.size()); | 776 abandoned_push_streams.Add(unclaimed_pushed_streams_.size()); |
| 791 } | 777 } |
| 792 | 778 |
| 793 for (int i = 0;i < NUM_PRIORITIES;++i) { | 779 for (int i = 0;i < NUM_PRIORITIES;++i) { |
| 794 while (!create_stream_queues_[i].empty()) { | 780 while (!create_stream_queues_[i].empty()) { |
| 795 PendingCreateStream& pending_create = create_stream_queues_[i].front(); | 781 PendingCreateStream& pending_create = create_stream_queues_[i].front(); |
| 796 pending_create.callback->Run(ERR_ABORTED); | 782 pending_create.callback->Run(ERR_ABORTED); |
| 797 create_stream_queues_[i].pop(); | 783 create_stream_queues_[i].pop(); |
| 798 } | 784 } |
| 799 } | 785 } |
| 800 | 786 |
| 801 while (!active_streams_.empty()) { | 787 while (!active_streams_.empty()) { |
| 802 ActiveStreamMap::iterator it = active_streams_.begin(); | 788 ActiveStreamMap::iterator it = active_streams_.begin(); |
| 803 const scoped_refptr<SpdyStream>& stream = it->second; | 789 const scoped_refptr<SpdyStream>& stream = it->second; |
| 804 DCHECK(stream); | 790 DCHECK(stream); |
| 805 LOG(ERROR) << "ABANDONED (stream_id=" << stream->stream_id() | 791 LOG(ERROR) << "ABANDONED (stream_id=" << stream->stream_id() |
| 806 << "): " << stream->path(); | 792 << "): " << stream->path(); |
| 807 DeleteStream(stream->stream_id(), status); | 793 DeleteStream(stream->stream_id(), status); |
| 808 } | 794 } |
| 809 | 795 |
| 810 // TODO(erikchen): ideally stream->OnClose() is only ever called by | |
| 811 // DeleteStream, but pending streams fall into their own category for now. | |
| 812 PendingStreamMap::iterator it; | |
| 813 for (it = pending_streams_.begin(); it != pending_streams_.end(); ++it) { | |
| 814 const scoped_refptr<SpdyStream>& stream = it->second; | |
| 815 if (stream) | |
| 816 stream->OnClose(ERR_ABORTED); | |
| 817 } | |
| 818 pending_streams_.clear(); | |
| 819 | |
| 820 // We also need to drain the queue. | 796 // We also need to drain the queue. |
| 821 while (queue_.size()) | 797 while (queue_.size()) |
| 822 queue_.pop(); | 798 queue_.pop(); |
| 823 } | 799 } |
| 824 | 800 |
| 825 int SpdySession::GetNewStreamId() { | 801 int SpdySession::GetNewStreamId() { |
| 826 int id = stream_hi_water_mark_; | 802 int id = stream_hi_water_mark_; |
| 827 stream_hi_water_mark_ += 2; | 803 stream_hi_water_mark_ += 2; |
| 828 if (stream_hi_water_mark_ > 0x7fff) | 804 if (stream_hi_water_mark_ > 0x7fff) |
| 829 stream_hi_water_mark_ = 1; | 805 stream_hi_water_mark_ = 1; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 } | 838 } |
| 863 | 839 |
| 864 void SpdySession::ActivateStream(SpdyStream* stream) { | 840 void SpdySession::ActivateStream(SpdyStream* stream) { |
| 865 const spdy::SpdyStreamId id = stream->stream_id(); | 841 const spdy::SpdyStreamId id = stream->stream_id(); |
| 866 DCHECK(!IsStreamActive(id)); | 842 DCHECK(!IsStreamActive(id)); |
| 867 | 843 |
| 868 active_streams_[id] = stream; | 844 active_streams_[id] = stream; |
| 869 } | 845 } |
| 870 | 846 |
| 871 void SpdySession::DeleteStream(spdy::SpdyStreamId id, int status) { | 847 void SpdySession::DeleteStream(spdy::SpdyStreamId id, int status) { |
| 872 // Remove the stream from pushed_streams_ and active_streams_. | 848 // Remove the stream from unclaimed_pushed_streams_ and active_streams_. |
| 873 ActivePushedStreamList::iterator it; | 849 PushedStreamMap::iterator it; |
| 874 for (it = pushed_streams_.begin(); it != pushed_streams_.end(); ++it) { | 850 for (it = unclaimed_pushed_streams_.begin(); |
| 875 scoped_refptr<SpdyStream> curr = *it; | 851 it != unclaimed_pushed_streams_.end(); ++it) { |
| 852 scoped_refptr<SpdyStream> curr = it->second; |
| 876 if (id == curr->stream_id()) { | 853 if (id == curr->stream_id()) { |
| 877 pushed_streams_.erase(it); | 854 unclaimed_pushed_streams_.erase(it); |
| 878 break; | 855 break; |
| 879 } | 856 } |
| 880 } | 857 } |
| 881 | 858 |
| 882 // The stream might have been deleted. | 859 // The stream might have been deleted. |
| 883 ActiveStreamMap::iterator it2 = active_streams_.find(id); | 860 ActiveStreamMap::iterator it2 = active_streams_.find(id); |
| 884 if (it2 == active_streams_.end()) | 861 if (it2 == active_streams_.end()) |
| 885 return; | 862 return; |
| 886 | 863 |
| 887 // If this is an active stream, call the callback. | 864 // If this is an active stream, call the callback. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 898 in_session_pool_ = false; | 875 in_session_pool_ = false; |
| 899 } | 876 } |
| 900 } | 877 } |
| 901 | 878 |
| 902 scoped_refptr<SpdyStream> SpdySession::GetActivePushStream( | 879 scoped_refptr<SpdyStream> SpdySession::GetActivePushStream( |
| 903 const std::string& path) { | 880 const std::string& path) { |
| 904 static StatsCounter used_push_streams("spdy.claimed_push_streams"); | 881 static StatsCounter used_push_streams("spdy.claimed_push_streams"); |
| 905 | 882 |
| 906 LOG(INFO) << "Looking for push stream: " << path; | 883 LOG(INFO) << "Looking for push stream: " << path; |
| 907 | 884 |
| 908 scoped_refptr<SpdyStream> stream; | 885 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(path); |
| 909 | 886 if (it != unclaimed_pushed_streams_.end()) { |
| 910 // We just walk a linear list here. | 887 LOG(INFO) << "Push stream: " << path << " found."; |
| 911 ActivePushedStreamList::iterator it; | 888 net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM, NULL); |
| 912 for (it = pushed_streams_.begin(); it != pushed_streams_.end(); ++it) { | 889 scoped_refptr<SpdyStream> stream = it->second; |
| 913 stream = *it; | 890 unclaimed_pushed_streams_.erase(it); |
| 914 if (path == stream->path()) { | 891 used_push_streams.Increment(); |
| 915 CHECK(stream->pushed()); | 892 return stream; |
| 916 pushed_streams_.erase(it); | |
| 917 used_push_streams.Increment(); | |
| 918 LOG(INFO) << "Push Stream Claim for: " << path; | |
| 919 return stream; | |
| 920 } | |
| 921 } | 893 } |
| 922 | 894 else { |
| 923 return NULL; | 895 LOG(INFO) << "Push stream: " << path << " not found."; |
| 896 return NULL; |
| 897 } |
| 924 } | 898 } |
| 925 | 899 |
| 926 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, bool* was_npn_negotiated) { | 900 bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, bool* was_npn_negotiated) { |
| 927 if (is_secure_) { | 901 if (is_secure_) { |
| 928 SSLClientSocket* ssl_socket = | 902 SSLClientSocket* ssl_socket = |
| 929 reinterpret_cast<SSLClientSocket*>(connection_->socket()); | 903 reinterpret_cast<SSLClientSocket*>(connection_->socket()); |
| 930 ssl_socket->GetSSLInfo(ssl_info); | 904 ssl_socket->GetSSLInfo(ssl_info); |
| 931 *was_npn_negotiated = ssl_socket->wasNpnNegotiated(); | 905 *was_npn_negotiated = ssl_socket->wasNpnNegotiated(); |
| 932 return true; | 906 return true; |
| 933 } | 907 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 964 const spdy::SpdyStreamId stream_id = stream->stream_id(); | 938 const spdy::SpdyStreamId stream_id = stream->stream_id(); |
| 965 DeleteStream(stream_id, rv); | 939 DeleteStream(stream_id, rv); |
| 966 return false; | 940 return false; |
| 967 } | 941 } |
| 968 return true; | 942 return true; |
| 969 } | 943 } |
| 970 | 944 |
| 971 void SpdySession::OnSyn(const spdy::SpdySynStreamControlFrame& frame, | 945 void SpdySession::OnSyn(const spdy::SpdySynStreamControlFrame& frame, |
| 972 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { | 946 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { |
| 973 spdy::SpdyStreamId stream_id = frame.stream_id(); | 947 spdy::SpdyStreamId stream_id = frame.stream_id(); |
| 974 | 948 spdy::SpdyStreamId associated_stream_id = frame.associated_stream_id(); |
| 975 LOG(INFO) << "Spdy SynStream for stream " << stream_id; | 949 LOG(INFO) << "Spdy SynStream for stream " << stream_id |
| 976 | 950 << " with associated stream " << associated_stream_id; |
| 977 // Server-initiated streams should have even sequence numbers. | 951 // Server-initiated streams should have even sequence numbers. |
| 978 if ((stream_id & 0x1) != 0) { | 952 if ((stream_id & 0x1) != 0) { |
| 979 LOG(ERROR) << "Received invalid OnSyn stream id " << stream_id; | 953 LOG(ERROR) << "Received invalid OnSyn stream id " << stream_id; |
| 980 return; | 954 return; |
| 981 } | 955 } |
| 982 | 956 |
| 983 if (IsStreamActive(stream_id)) { | 957 if (IsStreamActive(stream_id)) { |
| 984 LOG(ERROR) << "Received OnSyn for active stream " << stream_id; | 958 LOG(ERROR) << "Received OnSyn for active stream " << stream_id; |
| 985 return; | 959 return; |
| 986 } | 960 } |
| 987 | 961 |
| 962 if (associated_stream_id == 0) { |
| 963 LOG(ERROR) << "Received invalid OnSyn associated stream id " |
| 964 << associated_stream_id |
| 965 << " for stream " << stream_id; |
| 966 ResetStream(stream_id, spdy::INVALID_STREAM); |
| 967 return; |
| 968 } |
| 969 |
| 988 streams_pushed_count_++; | 970 streams_pushed_count_++; |
| 989 | 971 |
| 990 LOG(INFO) << "SpdySession: Syn received for stream: " << stream_id; | 972 LOG(INFO) << "SpdySession: Syn received for stream: " << stream_id; |
| 991 | 973 |
| 992 LOG(INFO) << "SPDY SYN RESPONSE HEADERS -----------------------"; | 974 LOG(INFO) << "SPDY SYN RESPONSE HEADERS -----------------------"; |
| 993 DumpSpdyHeaders(*headers); | 975 DumpSpdyHeaders(*headers); |
| 994 | 976 |
| 995 // TODO(mbelshe): DCHECK that this is a GET method? | 977 // TODO(mbelshe): DCHECK that this is a GET method? |
| 996 | 978 |
| 997 const std::string& path = ContainsKey(*headers, "path") ? | 979 const std::string& path = ContainsKey(*headers, "path") ? |
| 998 headers->find("path")->second : ""; | 980 headers->find("path")->second : ""; |
| 999 | 981 |
| 1000 // Verify that the response had a URL for us. | 982 // Verify that the response had a URL for us. |
| 1001 DCHECK(!path.empty()); | |
| 1002 if (path.empty()) { | 983 if (path.empty()) { |
| 984 ResetStream(stream_id, spdy::PROTOCOL_ERROR); |
| 1003 LOG(WARNING) << "Pushed stream did not contain a path."; | 985 LOG(WARNING) << "Pushed stream did not contain a path."; |
| 1004 return; | 986 return; |
| 1005 } | 987 } |
| 1006 | 988 |
| 1007 // Only HTTP push a stream. | 989 if (!IsStreamActive(associated_stream_id)) { |
| 990 LOG(ERROR) << "Received OnSyn with inactive associated stream " |
| 991 << associated_stream_id; |
| 992 ResetStream(stream_id, spdy::INVALID_ASSOCIATED_STREAM); |
| 993 return; |
| 994 } |
| 995 |
| 1008 scoped_refptr<SpdyStream> stream; | 996 scoped_refptr<SpdyStream> stream; |
| 1009 | 997 |
| 1010 // Check if we already have a delegate awaiting this stream. | 998 stream = new SpdyStream(this, stream_id, true); |
| 1011 PendingStreamMap::iterator it; | 999 |
| 1012 it = pending_streams_.find(path); | 1000 if (net_log_.HasListener()) { |
| 1013 if (it != pending_streams_.end()) { | 1001 net_log_.AddEvent( |
| 1014 stream = it->second; | 1002 NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, |
| 1015 pending_streams_.erase(it); | 1003 new NetLogSpdySynParameter( |
| 1004 headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), |
| 1005 stream_id)); |
| 1016 } | 1006 } |
| 1017 | 1007 |
| 1018 if (stream) { | 1008 // TODO(erikchen): Actually do something with the associated id. |
| 1019 CHECK(stream->pushed()); | |
| 1020 CHECK_EQ(0u, stream->stream_id()); | |
| 1021 stream->set_stream_id(stream_id); | |
| 1022 const BoundNetLog& log = stream->net_log(); | |
| 1023 if (log.HasListener()) { | |
| 1024 log.AddEvent( | |
| 1025 NetLog::TYPE_SPDY_STREAM_PUSHED_SYN_STREAM, | |
| 1026 new NetLogSpdySynParameter( | |
| 1027 headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), | |
| 1028 stream_id)); | |
| 1029 } | |
| 1030 } else { | |
| 1031 stream = new SpdyStream(this, stream_id, true); | |
| 1032 | 1009 |
| 1033 if (net_log_.HasListener()) { | 1010 stream->set_path(path); |
| 1034 net_log_.AddEvent( | 1011 |
| 1035 NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, | 1012 // There should not be an existing pushed stream with the same path. |
| 1036 new NetLogSpdySynParameter( | 1013 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(path); |
| 1037 headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), | 1014 if (it != unclaimed_pushed_streams_.end()) { |
| 1038 stream_id)); | 1015 LOG(ERROR) << "Received duplicate pushed stream with path: " << path; |
| 1039 } | 1016 ResetStream(stream_id, spdy::PROTOCOL_ERROR); |
| 1040 } | 1017 } |
| 1041 | 1018 unclaimed_pushed_streams_[path] = stream; |
| 1042 pushed_streams_.push_back(stream); | |
| 1043 | 1019 |
| 1044 // Activate a stream and parse the headers. | 1020 // Activate a stream and parse the headers. |
| 1045 ActivateStream(stream); | 1021 ActivateStream(stream); |
| 1046 | 1022 |
| 1047 stream->set_path(path); | 1023 // Parse the headers. |
| 1048 | |
| 1049 if (!Respond(*headers, stream)) | 1024 if (!Respond(*headers, stream)) |
| 1050 return; | 1025 return; |
| 1051 | 1026 |
| 1052 LOG(INFO) << "Got pushed stream for " << stream->path(); | 1027 LOG(INFO) << "Got pushed stream for " << stream->path(); |
| 1053 | 1028 |
| 1054 static StatsCounter push_requests("spdy.pushed_streams"); | 1029 static StatsCounter push_requests("spdy.pushed_streams"); |
| 1055 push_requests.Increment(); | 1030 push_requests.Increment(); |
| 1056 } | 1031 } |
| 1057 | 1032 |
| 1058 void SpdySession::OnSynReply(const spdy::SpdySynReplyControlFrame& frame, | 1033 void SpdySession::OnSynReply(const spdy::SpdySynReplyControlFrame& frame, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1074 CHECK_EQ(stream->stream_id(), stream_id); | 1049 CHECK_EQ(stream->stream_id(), stream_id); |
| 1075 CHECK(!stream->cancelled()); | 1050 CHECK(!stream->cancelled()); |
| 1076 | 1051 |
| 1077 if (stream->syn_reply_received()) { | 1052 if (stream->syn_reply_received()) { |
| 1078 LOG(WARNING) << "Received duplicate SYN_REPLY for stream " << stream_id; | 1053 LOG(WARNING) << "Received duplicate SYN_REPLY for stream " << stream_id; |
| 1079 CloseStream(stream->stream_id(), ERR_SPDY_PROTOCOL_ERROR); | 1054 CloseStream(stream->stream_id(), ERR_SPDY_PROTOCOL_ERROR); |
| 1080 return; | 1055 return; |
| 1081 } | 1056 } |
| 1082 stream->set_syn_reply_received(); | 1057 stream->set_syn_reply_received(); |
| 1083 | 1058 |
| 1084 // We record content declared as being pushed so that we don't | |
| 1085 // request a duplicate stream which is already scheduled to be | |
| 1086 // sent to us. | |
| 1087 spdy::SpdyHeaderBlock::const_iterator it; | |
| 1088 it = headers->find("x-associated-content"); | |
| 1089 if (it != headers->end()) { | |
| 1090 const std::string& content = it->second; | |
| 1091 std::string::size_type start = 0; | |
| 1092 std::string::size_type end = 0; | |
| 1093 do { | |
| 1094 end = content.find("||", start); | |
| 1095 if (end == std::string::npos) | |
| 1096 end = content.length(); | |
| 1097 std::string url = content.substr(start, end - start); | |
| 1098 std::string::size_type pos = url.find("??"); | |
| 1099 if (pos == std::string::npos) | |
| 1100 break; | |
| 1101 url = url.substr(pos + 2); | |
| 1102 GURL gurl(url); | |
| 1103 std::string path = gurl.PathForRequest(); | |
| 1104 if (path.length()) | |
| 1105 pending_streams_[path] = NULL; | |
| 1106 else | |
| 1107 LOG(INFO) << "Invalid X-Associated-Content path: " << url; | |
| 1108 start = end + 2; | |
| 1109 } while (start < content.length()); | |
| 1110 } | |
| 1111 | |
| 1112 const BoundNetLog& log = stream->net_log(); | 1059 const BoundNetLog& log = stream->net_log(); |
| 1113 if (log.HasListener()) { | 1060 if (log.HasListener()) { |
| 1114 log.AddEvent( | 1061 log.AddEvent( |
| 1115 NetLog::TYPE_SPDY_STREAM_SYN_REPLY, | 1062 NetLog::TYPE_SPDY_STREAM_SYN_REPLY, |
| 1116 new NetLogSpdySynParameter( | 1063 new NetLogSpdySynParameter( |
| 1117 headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), | 1064 headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), |
| 1118 stream_id)); | 1065 stream_id)); |
| 1119 } | 1066 } |
| 1120 | 1067 |
| 1121 Respond(*headers, stream); | 1068 Respond(*headers, stream); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1144 | 1091 |
| 1145 switch (type) { | 1092 switch (type) { |
| 1146 case spdy::GOAWAY: | 1093 case spdy::GOAWAY: |
| 1147 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame)); | 1094 OnGoAway(*reinterpret_cast<const spdy::SpdyGoAwayControlFrame*>(frame)); |
| 1148 break; | 1095 break; |
| 1149 case spdy::SETTINGS: | 1096 case spdy::SETTINGS: |
| 1150 OnSettings( | 1097 OnSettings( |
| 1151 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); | 1098 *reinterpret_cast<const spdy::SpdySettingsControlFrame*>(frame)); |
| 1152 break; | 1099 break; |
| 1153 case spdy::RST_STREAM: | 1100 case spdy::RST_STREAM: |
| 1154 OnFin(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); | 1101 OnRst(*reinterpret_cast<const spdy::SpdyRstStreamControlFrame*>(frame)); |
| 1155 break; | 1102 break; |
| 1156 case spdy::SYN_STREAM: | 1103 case spdy::SYN_STREAM: |
| 1157 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), | 1104 OnSyn(*reinterpret_cast<const spdy::SpdySynStreamControlFrame*>(frame), |
| 1158 headers); | 1105 headers); |
| 1159 break; | 1106 break; |
| 1160 case spdy::SYN_REPLY: | 1107 case spdy::SYN_REPLY: |
| 1161 OnSynReply( | 1108 OnSynReply( |
| 1162 *reinterpret_cast<const spdy::SpdySynReplyControlFrame*>(frame), | 1109 *reinterpret_cast<const spdy::SpdySynReplyControlFrame*>(frame), |
| 1163 headers); | 1110 headers); |
| 1164 break; | 1111 break; |
| 1165 case spdy::WINDOW_UPDATE: | 1112 case spdy::WINDOW_UPDATE: |
| 1166 OnWindowUpdate( | 1113 OnWindowUpdate( |
| 1167 *reinterpret_cast<const spdy::SpdyWindowUpdateControlFrame*>(frame)); | 1114 *reinterpret_cast<const spdy::SpdyWindowUpdateControlFrame*>(frame)); |
| 1168 break; | 1115 break; |
| 1169 default: | 1116 default: |
| 1170 DCHECK(false); // Error! | 1117 DCHECK(false); // Error! |
| 1171 } | 1118 } |
| 1172 } | 1119 } |
| 1173 | 1120 |
| 1174 void SpdySession::OnFin(const spdy::SpdyRstStreamControlFrame& frame) { | 1121 void SpdySession::OnRst(const spdy::SpdyRstStreamControlFrame& frame) { |
| 1175 spdy::SpdyStreamId stream_id = frame.stream_id(); | 1122 spdy::SpdyStreamId stream_id = frame.stream_id(); |
| 1176 LOG(INFO) << "Spdy Fin for stream " << stream_id; | 1123 LOG(INFO) << "Spdy Fin for stream " << stream_id; |
| 1177 | 1124 |
| 1178 bool valid_stream = IsStreamActive(stream_id); | 1125 bool valid_stream = IsStreamActive(stream_id); |
| 1179 if (!valid_stream) { | 1126 if (!valid_stream) { |
| 1180 // NOTE: it may just be that the stream was cancelled. | 1127 // NOTE: it may just be that the stream was cancelled. |
| 1181 LOG(WARNING) << "Received FIN for invalid stream" << stream_id; | 1128 LOG(WARNING) << "Received FIN for invalid stream" << stream_id; |
| 1182 return; | 1129 return; |
| 1183 } | 1130 } |
| 1184 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 1131 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1334 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRetransRate", | 1281 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRetransRate", |
| 1335 setting.second, | 1282 setting.second, |
| 1336 1, 100, 50); | 1283 1, 100, 50); |
| 1337 break; | 1284 break; |
| 1338 } | 1285 } |
| 1339 } | 1286 } |
| 1340 } | 1287 } |
| 1341 } | 1288 } |
| 1342 | 1289 |
| 1343 } // namespace net | 1290 } // namespace net |
| OLD | NEW |