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 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 TimeFunc time_func, | 583 TimeFunc time_func, |
584 const HostPortPair& trusted_spdy_proxy, | 584 const HostPortPair& trusted_spdy_proxy, |
585 NetLog* net_log) | 585 NetLog* net_log) |
586 : in_io_loop_(false), | 586 : in_io_loop_(false), |
587 spdy_session_key_(spdy_session_key), | 587 spdy_session_key_(spdy_session_key), |
588 pool_(NULL), | 588 pool_(NULL), |
589 http_server_properties_(http_server_properties), | 589 http_server_properties_(http_server_properties), |
590 transport_security_state_(transport_security_state), | 590 transport_security_state_(transport_security_state), |
591 read_buffer_(new IOBuffer(kReadBufferSize)), | 591 read_buffer_(new IOBuffer(kReadBufferSize)), |
592 stream_hi_water_mark_(kFirstStreamId), | 592 stream_hi_water_mark_(kFirstStreamId), |
| 593 last_accepted_push_stream_id_(0), |
593 num_pushed_streams_(0u), | 594 num_pushed_streams_(0u), |
594 num_active_pushed_streams_(0u), | 595 num_active_pushed_streams_(0u), |
595 in_flight_write_frame_type_(DATA), | 596 in_flight_write_frame_type_(DATA), |
596 in_flight_write_frame_size_(0), | 597 in_flight_write_frame_size_(0), |
597 is_secure_(false), | 598 is_secure_(false), |
598 certificate_error_code_(OK), | 599 certificate_error_code_(OK), |
599 availability_state_(STATE_AVAILABLE), | 600 availability_state_(STATE_AVAILABLE), |
600 read_state_(READ_STATE_DO_READ), | 601 read_state_(READ_STATE_DO_READ), |
601 write_state_(WRITE_STATE_IDLE), | 602 write_state_(WRITE_STATE_IDLE), |
602 error_on_close_(OK), | 603 error_on_close_(OK), |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1670 // and why. Don't GOAWAY on a graceful or idle close, as that may | 1671 // and why. Don't GOAWAY on a graceful or idle close, as that may |
1671 // unnecessarily wake the radio. We could technically GOAWAY on network errors | 1672 // unnecessarily wake the radio. We could technically GOAWAY on network errors |
1672 // (we'll probably fail to actually write it, but that's okay), however many | 1673 // (we'll probably fail to actually write it, but that's okay), however many |
1673 // unit-tests would need to be updated. | 1674 // unit-tests would need to be updated. |
1674 if (err != OK && | 1675 if (err != OK && |
1675 err != ERR_ABORTED && // Used by SpdySessionPool to close idle sessions. | 1676 err != ERR_ABORTED && // Used by SpdySessionPool to close idle sessions. |
1676 err != ERR_NETWORK_CHANGED && // Used to deprecate sessions on IP change. | 1677 err != ERR_NETWORK_CHANGED && // Used to deprecate sessions on IP change. |
1677 err != ERR_SOCKET_NOT_CONNECTED && | 1678 err != ERR_SOCKET_NOT_CONNECTED && |
1678 err != ERR_CONNECTION_CLOSED && err != ERR_CONNECTION_RESET) { | 1679 err != ERR_CONNECTION_CLOSED && err != ERR_CONNECTION_RESET) { |
1679 // Enqueue a GOAWAY to inform the peer of why we're closing the connection. | 1680 // Enqueue a GOAWAY to inform the peer of why we're closing the connection. |
1680 SpdyGoAwayIR goaway_ir(0, // Last accepted stream ID. | 1681 SpdyGoAwayIR goaway_ir(last_accepted_push_stream_id_, |
1681 MapNetErrorToGoAwayStatus(err), | 1682 MapNetErrorToGoAwayStatus(err), |
1682 description); | 1683 description); |
1683 EnqueueSessionWrite(HIGHEST, | 1684 EnqueueSessionWrite(HIGHEST, |
1684 GOAWAY, | 1685 GOAWAY, |
1685 scoped_ptr<SpdyFrame>( | 1686 scoped_ptr<SpdyFrame>( |
1686 buffered_spdy_framer_->SerializeFrame(goaway_ir))); | 1687 buffered_spdy_framer_->SerializeFrame(goaway_ir))); |
1687 } | 1688 } |
1688 | 1689 |
1689 availability_state_ = STATE_DRAINING; | 1690 availability_state_ = STATE_DRAINING; |
1690 error_on_close_ = err; | 1691 error_on_close_ = err; |
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2353 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); | 2354 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); |
2354 } | 2355 } |
2355 } | 2356 } |
2356 } | 2357 } |
2357 | 2358 |
2358 bool SpdySession::OnUnknownFrame(SpdyStreamId stream_id, int frame_type) { | 2359 bool SpdySession::OnUnknownFrame(SpdyStreamId stream_id, int frame_type) { |
2359 // Validate stream id. | 2360 // Validate stream id. |
2360 // Was the frame sent on a stream id that has not been used in this session? | 2361 // Was the frame sent on a stream id that has not been used in this session? |
2361 if (stream_id % 2 == 1 && stream_id > stream_hi_water_mark_) | 2362 if (stream_id % 2 == 1 && stream_id > stream_hi_water_mark_) |
2362 return false; | 2363 return false; |
2363 // TODO(bnc): Track highest id for server initiated streams. | 2364 |
| 2365 if (stream_id % 2 == 0 && stream_id > last_accepted_push_stream_id_) |
| 2366 return false; |
| 2367 |
2364 return true; | 2368 return true; |
2365 } | 2369 } |
2366 | 2370 |
2367 void SpdySession::OnRstStream(SpdyStreamId stream_id, | 2371 void SpdySession::OnRstStream(SpdyStreamId stream_id, |
2368 SpdyRstStreamStatus status) { | 2372 SpdyRstStreamStatus status) { |
2369 CHECK(in_io_loop_); | 2373 CHECK(in_io_loop_); |
2370 | 2374 |
2371 std::string description; | 2375 std::string description; |
2372 net_log().AddEvent( | 2376 net_log().AddEvent( |
2373 NetLog::TYPE_SPDY_SESSION_RST_STREAM, | 2377 NetLog::TYPE_SPDY_SESSION_RST_STREAM, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2514 } | 2518 } |
2515 } | 2519 } |
2516 | 2520 |
2517 bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id, | 2521 bool SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
2518 SpdyStreamId associated_stream_id, | 2522 SpdyStreamId associated_stream_id, |
2519 SpdyPriority priority, | 2523 SpdyPriority priority, |
2520 const SpdyHeaderBlock& headers) { | 2524 const SpdyHeaderBlock& headers) { |
2521 // Server-initiated streams should have even sequence numbers. | 2525 // Server-initiated streams should have even sequence numbers. |
2522 if ((stream_id & 0x1) != 0) { | 2526 if ((stream_id & 0x1) != 0) { |
2523 LOG(WARNING) << "Received invalid push stream id " << stream_id; | 2527 LOG(WARNING) << "Received invalid push stream id " << stream_id; |
| 2528 if (GetProtocolVersion() > SPDY2) |
| 2529 CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "Odd push stream id."); |
2524 return false; | 2530 return false; |
2525 } | 2531 } |
2526 | 2532 |
| 2533 if (GetProtocolVersion() > SPDY2) { |
| 2534 if (stream_id <= last_accepted_push_stream_id_) { |
| 2535 LOG(WARNING) << "Received push stream id lesser or equal to the last " |
| 2536 << "accepted before " << stream_id; |
| 2537 CloseSessionOnError( |
| 2538 ERR_SPDY_PROTOCOL_ERROR, |
| 2539 "New push stream id must be greater than the last accepted."); |
| 2540 return false; |
| 2541 } |
| 2542 } |
| 2543 |
2527 if (IsStreamActive(stream_id)) { | 2544 if (IsStreamActive(stream_id)) { |
| 2545 // For SPDY3 and higher we should not get here, we'll start going away |
| 2546 // earlier on |last_seen_push_stream_id_| check. |
| 2547 CHECK_GT(SPDY3, GetProtocolVersion()); |
2528 LOG(WARNING) << "Received push for active stream " << stream_id; | 2548 LOG(WARNING) << "Received push for active stream " << stream_id; |
2529 return false; | 2549 return false; |
2530 } | 2550 } |
2531 | 2551 |
| 2552 last_accepted_push_stream_id_ = stream_id; |
| 2553 |
2532 RequestPriority request_priority = | 2554 RequestPriority request_priority = |
2533 ConvertSpdyPriorityToRequestPriority(priority, GetProtocolVersion()); | 2555 ConvertSpdyPriorityToRequestPriority(priority, GetProtocolVersion()); |
2534 | 2556 |
2535 if (availability_state_ == STATE_GOING_AWAY) { | 2557 if (availability_state_ == STATE_GOING_AWAY) { |
2536 // TODO(akalin): This behavior isn't in the SPDY spec, although it | 2558 // TODO(akalin): This behavior isn't in the SPDY spec, although it |
2537 // probably should be. | 2559 // probably should be. |
2538 EnqueueResetStreamFrame(stream_id, | 2560 EnqueueResetStreamFrame(stream_id, |
2539 request_priority, | 2561 request_priority, |
2540 RST_STREAM_REFUSED_STREAM, | 2562 RST_STREAM_REFUSED_STREAM, |
2541 "push stream request received when going away"); | 2563 "push stream request received when going away"); |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3207 if (!queue->empty()) { | 3229 if (!queue->empty()) { |
3208 SpdyStreamId stream_id = queue->front(); | 3230 SpdyStreamId stream_id = queue->front(); |
3209 queue->pop_front(); | 3231 queue->pop_front(); |
3210 return stream_id; | 3232 return stream_id; |
3211 } | 3233 } |
3212 } | 3234 } |
3213 return 0; | 3235 return 0; |
3214 } | 3236 } |
3215 | 3237 |
3216 } // namespace net | 3238 } // namespace net |
OLD | NEW |