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 <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 return OK; | 911 return OK; |
912 } | 912 } |
913 | 913 |
914 void SpdySession::CancelStreamRequest( | 914 void SpdySession::CancelStreamRequest( |
915 const base::WeakPtr<SpdyStreamRequest>& request) { | 915 const base::WeakPtr<SpdyStreamRequest>& request) { |
916 DCHECK(request); | 916 DCHECK(request); |
917 RequestPriority priority = request->priority(); | 917 RequestPriority priority = request->priority(); |
918 CHECK_GE(priority, MINIMUM_PRIORITY); | 918 CHECK_GE(priority, MINIMUM_PRIORITY); |
919 CHECK_LE(priority, MAXIMUM_PRIORITY); | 919 CHECK_LE(priority, MAXIMUM_PRIORITY); |
920 | 920 |
921 #if DCHECK_IS_ON | 921 #if DCHECK_IS_ON() |
922 // |request| should not be in a queue not matching its priority. | 922 // |request| should not be in a queue not matching its priority. |
923 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | 923 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { |
924 if (priority == i) | 924 if (priority == i) |
925 continue; | 925 continue; |
926 PendingStreamRequestQueue* queue = &pending_create_stream_queues_[i]; | 926 PendingStreamRequestQueue* queue = &pending_create_stream_queues_[i]; |
927 DCHECK(std::find_if(queue->begin(), | 927 DCHECK(std::find_if(queue->begin(), |
928 queue->end(), | 928 queue->end(), |
929 RequestEquals(request)) == queue->end()); | 929 RequestEquals(request)) == queue->end()); |
930 } | 930 } |
931 #endif | 931 #endif |
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1624 in_flight_write_frame_size_ = 0; | 1624 in_flight_write_frame_size_ = 0; |
1625 in_flight_write_stream_.reset(); | 1625 in_flight_write_stream_.reset(); |
1626 } | 1626 } |
1627 } | 1627 } |
1628 | 1628 |
1629 write_state_ = WRITE_STATE_DO_WRITE; | 1629 write_state_ = WRITE_STATE_DO_WRITE; |
1630 return OK; | 1630 return OK; |
1631 } | 1631 } |
1632 | 1632 |
1633 void SpdySession::DcheckGoingAway() const { | 1633 void SpdySession::DcheckGoingAway() const { |
1634 #if DCHECK_IS_ON | 1634 #if DCHECK_IS_ON() |
1635 DCHECK_GE(availability_state_, STATE_GOING_AWAY); | 1635 DCHECK_GE(availability_state_, STATE_GOING_AWAY); |
1636 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { | 1636 for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) { |
1637 DCHECK(pending_create_stream_queues_[i].empty()); | 1637 DCHECK(pending_create_stream_queues_[i].empty()); |
1638 } | 1638 } |
1639 DCHECK(created_streams_.empty()); | 1639 DCHECK(created_streams_.empty()); |
1640 #endif | 1640 #endif |
1641 } | 1641 } |
1642 | 1642 |
1643 void SpdySession::DcheckDraining() const { | 1643 void SpdySession::DcheckDraining() const { |
1644 DcheckGoingAway(); | 1644 DcheckGoingAway(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1698 DoDrainSession(OK, "Finished going away"); | 1698 DoDrainSession(OK, "Finished going away"); |
1699 } | 1699 } |
1700 } | 1700 } |
1701 | 1701 |
1702 void SpdySession::DoDrainSession(Error err, const std::string& description) { | 1702 void SpdySession::DoDrainSession(Error err, const std::string& description) { |
1703 if (availability_state_ == STATE_DRAINING) { | 1703 if (availability_state_ == STATE_DRAINING) { |
1704 return; | 1704 return; |
1705 } | 1705 } |
1706 MakeUnavailable(); | 1706 MakeUnavailable(); |
1707 | 1707 |
| 1708 // Mark host_port_pair requiring HTTP/1.1 for subsequent connections. |
| 1709 if (err == ERR_HTTP_1_1_REQUIRED) { |
| 1710 http_server_properties_->SetHTTP11Required(host_port_pair()); |
| 1711 } |
| 1712 |
1708 // If |err| indicates an error occurred, inform the peer that we're closing | 1713 // If |err| indicates an error occurred, inform the peer that we're closing |
1709 // and why. Don't GOAWAY on a graceful or idle close, as that may | 1714 // and why. Don't GOAWAY on a graceful or idle close, as that may |
1710 // unnecessarily wake the radio. We could technically GOAWAY on network errors | 1715 // unnecessarily wake the radio. We could technically GOAWAY on network errors |
1711 // (we'll probably fail to actually write it, but that's okay), however many | 1716 // (we'll probably fail to actually write it, but that's okay), however many |
1712 // unit-tests would need to be updated. | 1717 // unit-tests would need to be updated. |
1713 if (err != OK && | 1718 if (err != OK && |
1714 err != ERR_ABORTED && // Used by SpdySessionPool to close idle sessions. | 1719 err != ERR_ABORTED && // Used by SpdySessionPool to close idle sessions. |
1715 err != ERR_NETWORK_CHANGED && // Used to deprecate sessions on IP change. | 1720 err != ERR_NETWORK_CHANGED && // Used to deprecate sessions on IP change. |
1716 err != ERR_SOCKET_NOT_CONNECTED && | 1721 err != ERR_SOCKET_NOT_CONNECTED && err != ERR_HTTP_1_1_REQUIRED && |
1717 err != ERR_CONNECTION_CLOSED && err != ERR_CONNECTION_RESET) { | 1722 err != ERR_CONNECTION_CLOSED && err != ERR_CONNECTION_RESET) { |
1718 // Enqueue a GOAWAY to inform the peer of why we're closing the connection. | 1723 // Enqueue a GOAWAY to inform the peer of why we're closing the connection. |
1719 SpdyGoAwayIR goaway_ir(last_accepted_push_stream_id_, | 1724 SpdyGoAwayIR goaway_ir(last_accepted_push_stream_id_, |
1720 MapNetErrorToGoAwayStatus(err), | 1725 MapNetErrorToGoAwayStatus(err), |
1721 description); | 1726 description); |
1722 EnqueueSessionWrite(HIGHEST, | 1727 EnqueueSessionWrite(HIGHEST, |
1723 GOAWAY, | 1728 GOAWAY, |
1724 scoped_ptr<SpdyFrame>( | 1729 scoped_ptr<SpdyFrame>( |
1725 buffered_spdy_framer_->SerializeFrame(goaway_ir))); | 1730 buffered_spdy_framer_->SerializeFrame(goaway_ir))); |
1726 } | 1731 } |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2425 LOG(WARNING) << "Received RST for invalid stream" << stream_id; | 2430 LOG(WARNING) << "Received RST for invalid stream" << stream_id; |
2426 return; | 2431 return; |
2427 } | 2432 } |
2428 | 2433 |
2429 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2434 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
2430 | 2435 |
2431 if (status == 0) { | 2436 if (status == 0) { |
2432 it->second.stream->OnDataReceived(scoped_ptr<SpdyBuffer>()); | 2437 it->second.stream->OnDataReceived(scoped_ptr<SpdyBuffer>()); |
2433 } else if (status == RST_STREAM_REFUSED_STREAM) { | 2438 } else if (status == RST_STREAM_REFUSED_STREAM) { |
2434 CloseActiveStreamIterator(it, ERR_SPDY_SERVER_REFUSED_STREAM); | 2439 CloseActiveStreamIterator(it, ERR_SPDY_SERVER_REFUSED_STREAM); |
| 2440 } else if (status == RST_STREAM_HTTP_1_1_REQUIRED) { |
| 2441 // TODO(bnc): Record histogram with number of open streams capped at 50. |
| 2442 it->second.stream->LogStreamError( |
| 2443 ERR_HTTP_1_1_REQUIRED, |
| 2444 base::StringPrintf( |
| 2445 "SPDY session closed because of stream with status: %d", status)); |
| 2446 DoDrainSession(ERR_HTTP_1_1_REQUIRED, "HTTP_1_1_REQUIRED for stream."); |
2435 } else { | 2447 } else { |
2436 RecordProtocolErrorHistogram( | 2448 RecordProtocolErrorHistogram( |
2437 PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM); | 2449 PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM); |
2438 it->second.stream->LogStreamError( | 2450 it->second.stream->LogStreamError( |
2439 ERR_SPDY_PROTOCOL_ERROR, | 2451 ERR_SPDY_PROTOCOL_ERROR, |
2440 base::StringPrintf("SPDY stream closed with status: %d", status)); | 2452 base::StringPrintf("SPDY stream closed with status: %d", status)); |
2441 // TODO(mbelshe): Map from Spdy-protocol errors to something sensical. | 2453 // TODO(mbelshe): Map from Spdy-protocol errors to something sensical. |
2442 // For now, it doesn't matter much - it is a protocol error. | 2454 // For now, it doesn't matter much - it is a protocol error. |
2443 CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); | 2455 CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); |
2444 } | 2456 } |
2445 } | 2457 } |
2446 | 2458 |
2447 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, | 2459 void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, |
2448 SpdyGoAwayStatus status) { | 2460 SpdyGoAwayStatus status) { |
2449 CHECK(in_io_loop_); | 2461 CHECK(in_io_loop_); |
2450 | 2462 |
2451 // TODO(jgraettinger): UMA histogram on |status|. | 2463 // TODO(jgraettinger): UMA histogram on |status|. |
2452 | 2464 |
2453 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_GOAWAY, | 2465 net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_GOAWAY, |
2454 base::Bind(&NetLogSpdyGoAwayCallback, | 2466 base::Bind(&NetLogSpdyGoAwayCallback, |
2455 last_accepted_stream_id, | 2467 last_accepted_stream_id, |
2456 active_streams_.size(), | 2468 active_streams_.size(), |
2457 unclaimed_pushed_streams_.size(), | 2469 unclaimed_pushed_streams_.size(), |
2458 status)); | 2470 status)); |
2459 MakeUnavailable(); | 2471 MakeUnavailable(); |
2460 StartGoingAway(last_accepted_stream_id, ERR_ABORTED); | 2472 if (status == GOAWAY_HTTP_1_1_REQUIRED) { |
| 2473 // TODO(bnc): Record histogram with number of open streams capped at 50. |
| 2474 DoDrainSession(ERR_HTTP_1_1_REQUIRED, "HTTP_1_1_REQUIRED for stream."); |
| 2475 } else { |
| 2476 StartGoingAway(last_accepted_stream_id, ERR_ABORTED); |
| 2477 } |
2461 // This is to handle the case when we already don't have any active | 2478 // This is to handle the case when we already don't have any active |
2462 // streams (i.e., StartGoingAway() did nothing). Otherwise, we have | 2479 // streams (i.e., StartGoingAway() did nothing). Otherwise, we have |
2463 // active streams and so the last one being closed will finish the | 2480 // active streams and so the last one being closed will finish the |
2464 // going away process (see DeleteStream()). | 2481 // going away process (see DeleteStream()). |
2465 MaybeFinishGoingAway(); | 2482 MaybeFinishGoingAway(); |
2466 } | 2483 } |
2467 | 2484 |
2468 void SpdySession::OnPing(SpdyPingId unique_id, bool is_ack) { | 2485 void SpdySession::OnPing(SpdyPingId unique_id, bool is_ack) { |
2469 CHECK(in_io_loop_); | 2486 CHECK(in_io_loop_); |
2470 | 2487 |
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3241 void SpdySession::ResumeSendStalledStreams() { | 3258 void SpdySession::ResumeSendStalledStreams() { |
3242 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); | 3259 DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); |
3243 | 3260 |
3244 // We don't have to worry about new streams being queued, since | 3261 // We don't have to worry about new streams being queued, since |
3245 // doing so would cause IsSendStalled() to return true. But we do | 3262 // doing so would cause IsSendStalled() to return true. But we do |
3246 // have to worry about streams being closed, as well as ourselves | 3263 // have to worry about streams being closed, as well as ourselves |
3247 // being closed. | 3264 // being closed. |
3248 | 3265 |
3249 while (!IsSendStalled()) { | 3266 while (!IsSendStalled()) { |
3250 size_t old_size = 0; | 3267 size_t old_size = 0; |
3251 #if DCHECK_IS_ON | 3268 #if DCHECK_IS_ON() |
3252 old_size = GetTotalSize(stream_send_unstall_queue_); | 3269 old_size = GetTotalSize(stream_send_unstall_queue_); |
3253 #endif | 3270 #endif |
3254 | 3271 |
3255 SpdyStreamId stream_id = PopStreamToPossiblyResume(); | 3272 SpdyStreamId stream_id = PopStreamToPossiblyResume(); |
3256 if (stream_id == 0) | 3273 if (stream_id == 0) |
3257 break; | 3274 break; |
3258 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 3275 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
3259 // The stream may actually still be send-stalled after this (due | 3276 // The stream may actually still be send-stalled after this (due |
3260 // to its own send window) but that's okay -- it'll then be | 3277 // to its own send window) but that's okay -- it'll then be |
3261 // resumed once its send window increases. | 3278 // resumed once its send window increases. |
(...skipping 12 matching lines...) Expand all Loading... |
3274 if (!queue->empty()) { | 3291 if (!queue->empty()) { |
3275 SpdyStreamId stream_id = queue->front(); | 3292 SpdyStreamId stream_id = queue->front(); |
3276 queue->pop_front(); | 3293 queue->pop_front(); |
3277 return stream_id; | 3294 return stream_id; |
3278 } | 3295 } |
3279 } | 3296 } |
3280 return 0; | 3297 return 0; |
3281 } | 3298 } |
3282 | 3299 |
3283 } // namespace net | 3300 } // namespace net |
OLD | NEW |