| 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 |