| 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/chromium/spdy_session.h" | 5 #include "net/spdy/chromium/spdy_session.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 2105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2116 in_flight_write_stream_.reset(); | 2116 in_flight_write_stream_.reset(); |
| 2117 } | 2117 } |
| 2118 } | 2118 } |
| 2119 | 2119 |
| 2120 write_state_ = WRITE_STATE_DO_WRITE; | 2120 write_state_ = WRITE_STATE_DO_WRITE; |
| 2121 return OK; | 2121 return OK; |
| 2122 } | 2122 } |
| 2123 | 2123 |
| 2124 void SpdySession::SendInitialData() { | 2124 void SpdySession::SendInitialData() { |
| 2125 DCHECK(enable_sending_initial_data_); | 2125 DCHECK(enable_sending_initial_data_); |
| 2126 DCHECK(buffered_spdy_framer_.get()); |
| 2126 | 2127 |
| 2127 auto connection_header_prefix_frame = base::MakeUnique<SpdySerializedFrame>( | 2128 // Prepare initial SETTINGS frame. Only send settings that have a value |
| 2128 const_cast<char*>(kHttp2ConnectionHeaderPrefix), | 2129 // different from the protocol default value. |
| 2129 kHttp2ConnectionHeaderPrefixSize, false /* take_ownership */); | |
| 2130 // Count the prefix as part of the subsequent SETTINGS frame. | |
| 2131 EnqueueSessionWrite(HIGHEST, SpdyFrameType::SETTINGS, | |
| 2132 std::move(connection_header_prefix_frame)); | |
| 2133 | |
| 2134 // First, notify the server about the settings they should use when | |
| 2135 // communicating with us. Only send settings that have a value different from | |
| 2136 // the protocol default value. | |
| 2137 SettingsMap settings_map; | 2130 SettingsMap settings_map; |
| 2138 for (auto setting : initial_settings_) { | 2131 for (auto setting : initial_settings_) { |
| 2139 if (!IsSpdySettingAtDefaultInitialValue(setting.first, setting.second)) { | 2132 if (!IsSpdySettingAtDefaultInitialValue(setting.first, setting.second)) { |
| 2140 settings_map.insert(setting); | 2133 settings_map.insert(setting); |
| 2141 } | 2134 } |
| 2142 } | 2135 } |
| 2143 SendSettings(settings_map); | 2136 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_SETTINGS, |
| 2137 base::Bind(&NetLogSpdySendSettingsCallback, &settings_map)); |
| 2138 std::unique_ptr<SpdySerializedFrame> settings_frame( |
| 2139 buffered_spdy_framer_->CreateSettings(settings_map)); |
| 2144 | 2140 |
| 2145 // Next, notify the server about our initial recv window size. | 2141 // Prepare initial WINDOW_UPDATE frame. |
| 2146 // Bump up the receive window size to the real initial value. This | 2142 // Make sure |session_max_recv_window_size_ - session_recv_window_size_| |
| 2147 // has to go here since the WINDOW_UPDATE frame sent by | 2143 // does not underflow. |
| 2148 // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. | |
| 2149 // This condition implies that |session_max_recv_window_size_| - | |
| 2150 // |session_recv_window_size_| doesn't overflow. | |
| 2151 DCHECK_GE(session_max_recv_window_size_, session_recv_window_size_); | 2144 DCHECK_GE(session_max_recv_window_size_, session_recv_window_size_); |
| 2152 DCHECK_GE(session_recv_window_size_, 0); | 2145 DCHECK_GE(session_recv_window_size_, 0); |
| 2153 if (session_max_recv_window_size_ > session_recv_window_size_) { | 2146 DCHECK_EQ(0, session_unacked_recv_window_bytes_); |
| 2154 IncreaseRecvWindowSize(session_max_recv_window_size_ - | 2147 std::unique_ptr<SpdySerializedFrame> window_update_frame; |
| 2155 session_recv_window_size_); | 2148 const bool send_window_update = |
| 2149 session_max_recv_window_size_ > session_recv_window_size_; |
| 2150 if (send_window_update) { |
| 2151 const int32_t delta_window_size = |
| 2152 session_max_recv_window_size_ - session_recv_window_size_; |
| 2153 session_recv_window_size_ += delta_window_size; |
| 2154 net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_UPDATE_RECV_WINDOW, |
| 2155 base::Bind(&NetLogSpdySessionWindowUpdateCallback, |
| 2156 delta_window_size, session_recv_window_size_)); |
| 2157 |
| 2158 session_unacked_recv_window_bytes_ += delta_window_size; |
| 2159 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_WINDOW_UPDATE, |
| 2160 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, |
| 2161 kSessionFlowControlStreamId, |
| 2162 session_unacked_recv_window_bytes_)); |
| 2163 window_update_frame = buffered_spdy_framer_->CreateWindowUpdate( |
| 2164 kSessionFlowControlStreamId, session_unacked_recv_window_bytes_); |
| 2165 session_unacked_recv_window_bytes_ = 0; |
| 2156 } | 2166 } |
| 2157 } | |
| 2158 | 2167 |
| 2159 void SpdySession::SendSettings(const SettingsMap& settings) { | 2168 // Create a single frame to hold connection prefix, initial SETTINGS frame, |
| 2160 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_SETTINGS, | 2169 // and optional initial WINDOW_UPDATE frame, so that they are sent on the wire |
| 2161 base::Bind(&NetLogSpdySendSettingsCallback, &settings)); | 2170 // in a single packet. |
| 2162 // Create the SETTINGS frame and send it. | 2171 size_t initial_frame_size = |
| 2163 DCHECK(buffered_spdy_framer_.get()); | 2172 kHttp2ConnectionHeaderPrefixSize + settings_frame->size(); |
| 2164 std::unique_ptr<SpdySerializedFrame> settings_frame( | 2173 if (send_window_update) |
| 2165 buffered_spdy_framer_->CreateSettings(settings)); | 2174 initial_frame_size += window_update_frame->size(); |
| 2175 auto initial_frame_data = base::MakeUnique<char[]>(initial_frame_size); |
| 2176 size_t offset = 0; |
| 2177 |
| 2178 memcpy(initial_frame_data.get() + offset, kHttp2ConnectionHeaderPrefix, |
| 2179 kHttp2ConnectionHeaderPrefixSize); |
| 2180 offset += kHttp2ConnectionHeaderPrefixSize; |
| 2181 |
| 2182 memcpy(initial_frame_data.get() + offset, settings_frame->data(), |
| 2183 settings_frame->size()); |
| 2184 offset += settings_frame->size(); |
| 2185 |
| 2186 if (send_window_update) { |
| 2187 memcpy(initial_frame_data.get() + offset, window_update_frame->data(), |
| 2188 window_update_frame->size()); |
| 2189 } |
| 2190 |
| 2191 auto initial_frame = base::MakeUnique<SpdySerializedFrame>( |
| 2192 initial_frame_data.release(), initial_frame_size, |
| 2193 /* owns_buffer = */ true); |
| 2166 EnqueueSessionWrite(HIGHEST, SpdyFrameType::SETTINGS, | 2194 EnqueueSessionWrite(HIGHEST, SpdyFrameType::SETTINGS, |
| 2167 std::move(settings_frame)); | 2195 std::move(initial_frame)); |
| 2168 } | 2196 } |
| 2169 | 2197 |
| 2170 void SpdySession::HandleSetting(uint32_t id, uint32_t value) { | 2198 void SpdySession::HandleSetting(uint32_t id, uint32_t value) { |
| 2171 switch (id) { | 2199 switch (id) { |
| 2172 case SETTINGS_MAX_CONCURRENT_STREAMS: | 2200 case SETTINGS_MAX_CONCURRENT_STREAMS: |
| 2173 max_concurrent_streams_ = | 2201 max_concurrent_streams_ = |
| 2174 std::min(static_cast<size_t>(value), kMaxConcurrentStreamLimit); | 2202 std::min(static_cast<size_t>(value), kMaxConcurrentStreamLimit); |
| 2175 ProcessPendingStreamRequests(); | 2203 ProcessPendingStreamRequests(); |
| 2176 break; | 2204 break; |
| 2177 case SETTINGS_INITIAL_WINDOW_SIZE: { | 2205 case SETTINGS_INITIAL_WINDOW_SIZE: { |
| (...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3189 if (!queue->empty()) { | 3217 if (!queue->empty()) { |
| 3190 SpdyStreamId stream_id = queue->front(); | 3218 SpdyStreamId stream_id = queue->front(); |
| 3191 queue->pop_front(); | 3219 queue->pop_front(); |
| 3192 return stream_id; | 3220 return stream_id; |
| 3193 } | 3221 } |
| 3194 } | 3222 } |
| 3195 return 0; | 3223 return 0; |
| 3196 } | 3224 } |
| 3197 | 3225 |
| 3198 } // namespace net | 3226 } // namespace net |
| OLD | NEW |