spdy_session.cc revision 3551c9c881056c480085172ff9840cab31610854
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/field_trial.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/sparse_histogram.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_number_conversions.h" 215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 225e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/ec_private_key.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/ec_signature_creator.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/connection_type_histograms.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/asn1_util.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_server_properties.h" 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_buffer_producer.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_credential_builder.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_builder.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_utils.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_protocol.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session_pool.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_stream.h" 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/server_bound_cert_service.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kReadBufferSize = 8 * 1024; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultConnectionAtRiskOfLossSeconds = 10; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kHungIntervalSeconds = 10; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Always start at 1 for the first stream id. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SpdyStreamId kFirstStreamId = 1; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimum seconds that unclaimed pushed streams will be kept in memory. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinPushedStreamLifetimeSeconds = 300; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdySynCallback(const SpdyHeaderBlock* headers, 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool fin, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool unidirectional, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id, 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId associated_stream, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ListValue* headers_list = new base::ListValue(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SpdyHeaderBlock::const_iterator it = headers->begin(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != headers->end(); ++it) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) headers_list->Append(new base::StringValue(base::StringPrintf( 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "%s: %s", it->first.c_str(), 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (ShouldShowHttpHeaderValue( 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->first) ? it->second : "[elided]").c_str()))); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetBoolean("fin", fin); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetBoolean("unidirectional", unidirectional); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->Set("headers", headers_list); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("stream_id", stream_id); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (associated_stream) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("associated_stream", associated_stream); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdyCredentialCallback(size_t slot, 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string* origin, 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("slot", slot); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString("origin", *origin); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdySessionCloseCallback(int net_error, 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string* description, 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("net_error", net_error); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString("description", *description); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdySessionCallback(const HostPortProxyPair* host_pair, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString("host", host_pair->first.ToString()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString("proxy", host_pair->second.ToPacString()); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::Value* NetLogSpdySettingsCallback(const HostPortPair& host_port_pair, 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool clear_persisted, 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dict->SetString("host", host_port_pair.ToString()); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dict->SetBoolean("clear_persisted", clear_persisted); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return dict; 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdySettingCallback(SpdySettingsIds id, 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySettingsFlags flags, 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 value, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("id", id); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("flags", flags); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("value", value); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::Value* NetLogSpdySendSettingsCallback(const SettingsMap* settings, 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ListValue* settings_list = new base::ListValue(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SettingsMap::const_iterator it = settings->begin(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != settings->end(); ++it) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdySettingsIds id = it->first; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdySettingsFlags flags = it->second.first; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 value = it->second.second; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) settings_list->Append(new base::StringValue( 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf("[id:%u flags:%u value:%u]", id, flags, value))); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->Set("settings", settings_list); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdyWindowUpdateFrameCallback( 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id, 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 delta, 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("stream_id", static_cast<int>(stream_id)); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("delta", delta); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdySessionWindowUpdateCallback( 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 delta, 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 window_size, 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::DictionaryValue* dict = new base::DictionaryValue(); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dict->SetInteger("delta", delta); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dict->SetInteger("window_size", window_size); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return dict; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdyDataCallback(SpdyStreamId stream_id, 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int size, 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool fin, 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("stream_id", static_cast<int>(stream_id)); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("size", size); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dict->SetBoolean("fin", fin); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdyRstCallback(SpdyStreamId stream_id, 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int status, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string* description, 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("stream_id", static_cast<int>(stream_id)); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("status", status); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString("description", *description); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdyPingCallback(uint32 unique_id, 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* type, 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("unique_id", unique_id); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString("type", type); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogSpdyGoAwayCallback(SpdyStreamId last_stream_id, 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int active_streams, 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int unclaimed_streams, 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyGoAwayStatus status, 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::LogLevel /* log_level */) { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("last_accepted_stream_id", 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(last_stream_id)); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("active_streams", active_streams); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("unclaimed_streams", unclaimed_streams); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("status", static_cast<int>(status)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Helper function to return the total size of an array of objects 2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// with .size() member functions. 2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)template <typename T, size_t N> size_t GetTotalSize(const T (&arr)[N]) { 2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t total_size = 0; 2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0; i < N; ++i) { 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) total_size += arr[i].size(); 2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return total_size; 2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Helper class for std:find_if on STL container containing 2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// SpdyStreamRequest weak pointers. 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class RequestEquals { 2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public: 2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RequestEquals(const base::WeakPtr<SpdyStreamRequest>& request) 2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : request_(request) {} 2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool operator()(const base::WeakPtr<SpdyStreamRequest>& request) const { 2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return request_.get() == request.get(); 2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private: 2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::WeakPtr<SpdyStreamRequest> request_; 2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}; 2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum number of concurrent streams we will ever create. Even if 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the server permits more, we will never exceed this limit. 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxConcurrentStreamLimit = 256; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)SpdyStreamRequest::SpdyStreamRequest() : weak_ptr_factory_(this) { 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Reset(); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyStreamRequest::~SpdyStreamRequest() { 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelRequest(); 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SpdyStreamRequest::StartRequest( 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdyStreamType type, 249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const base::WeakPtr<SpdySession>& session, 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestPriority priority, 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BoundNetLog& net_log, 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CompletionCallback& callback) { 2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(session); 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!session_); 2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!stream_); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(callback_.is_null()); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) type_ = type; 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_ = session; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_ = url; 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority_ = priority; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_ = net_log; 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_ = callback; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 266a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream; 2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int rv = session->TryCreateStream(weak_ptr_factory_.GetWeakPtr(), &stream); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv == OK) { 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Reset(); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_ = stream; 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyStreamRequest::CancelRequest() { 2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (session_) 2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) session_->CancelStreamRequest(weak_ptr_factory_.GetWeakPtr()); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Reset(); 2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Do this to cancel any pending CompleteStreamRequest() tasks. 2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) weak_ptr_factory_.InvalidateWeakPtrs(); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 283a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)base::WeakPtr<SpdyStream> SpdyStreamRequest::ReleaseStream() { 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!session_); 285a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = stream_; 2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(stream); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Reset(); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return stream; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 291a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdyStreamRequest::OnRequestCompleteSuccess( 2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::WeakPtr<SpdyStream>& stream) { 2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(session_); 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!stream_); 295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(!callback_.is_null()); 296a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CompletionCallback callback = callback_; 297a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Reset(); 2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(stream); 2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) stream_ = stream; 300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) callback.Run(OK); 301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 302a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdyStreamRequest::OnRequestCompleteFailure(int rv) { 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(session_); 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!stream_); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!callback_.is_null()); 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CompletionCallback callback = callback_; 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Reset(); 309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK_NE(rv, OK); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(rv); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyStreamRequest::Reset() { 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) type_ = SPDY_BIDIRECTIONAL_STREAM; 315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch session_.reset(); 316a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream_.reset(); 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url_ = GURL(); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority_ = MINIMUM_PRIORITY; 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_ = BoundNetLog(); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Reset(); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySession::ActiveStreamInfo::ActiveStreamInfo() 324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : stream(NULL), 325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch waiting_for_syn_reply(false) {} 326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySession::ActiveStreamInfo::ActiveStreamInfo(SpdyStream* stream) 328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : stream(stream), 329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch waiting_for_syn_reply(stream->type() != SPDY_PUSH_STREAM) {} 330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySession::ActiveStreamInfo::~ActiveStreamInfo() {} 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySession::PushedStreamInfo::PushedStreamInfo() : stream_id(0) {} 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySession::PushedStreamInfo::PushedStreamInfo( 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamId stream_id, 337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeTicks creation_time) 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : stream_id(stream_id), 339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch creation_time(creation_time) {} 340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySession::PushedStreamInfo::~PushedStreamInfo() {} 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdySession::SpdySession( 344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const SpdySessionKey& spdy_session_key, 345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const base::WeakPtr<HttpServerProperties>& http_server_properties, 346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool verify_domain_authentication, 347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool enable_sending_initial_data, 348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool enable_credential_frames, 349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool enable_compression, 350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool enable_ping_based_connection_checking, 351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NextProto default_protocol, 352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch size_t stream_initial_recv_window_size, 353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch size_t initial_max_concurrent_streams, 354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch size_t max_concurrent_streams_limit, 355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TimeFunc time_func, 356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const HostPortPair& trusted_spdy_proxy, 357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NetLog* net_log) 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : weak_factory_(this), 359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_io_loop_(false), 36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_session_key_(spdy_session_key), 361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pool_(NULL), 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_server_properties_(http_server_properties), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_(new IOBuffer(kReadBufferSize)), 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_hi_water_mark_(kFirstStreamId), 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_type_(DATA), 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_size_(0), 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_secure_(false), 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certificate_error_code_(OK), 369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch availability_state_(STATE_AVAILABLE), 370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch read_state_(READ_STATE_DO_READ), 371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch write_state_(WRITE_STATE_IDLE), 372ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch error_on_close_(OK), 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_concurrent_streams_(initial_max_concurrent_streams == 0 ? 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kInitialMaxConcurrentStreams : 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initial_max_concurrent_streams), 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_concurrent_streams_limit_(max_concurrent_streams_limit == 0 ? 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kMaxConcurrentStreamLimit : 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) max_concurrent_streams_limit), 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_initiated_count_(0), 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_pushed_count_(0), 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_pushed_and_claimed_count_(0), 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_abandoned_count_(0), 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) total_bytes_received_(0), 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sent_settings_(false), 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_settings_(false), 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stalled_streams_(0), 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pings_in_flight_(0), 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_ping_id_(1), 389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch last_activity_time_(time_func()), 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check_ping_status_pending_(false), 391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) send_connection_header_prefix_(false), 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flow_control_state_(FLOW_CONTROL_NONE), 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_initial_send_window_size_(kSpdyStreamInitialWindowSize), 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_initial_recv_window_size_(stream_initial_recv_window_size == 0 ? 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kDefaultInitialRecvWindowSize : 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_initial_recv_window_size), 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_send_window_size_(0), 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_recv_window_size_(0), 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_unacked_recv_window_bytes_(0), 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)), 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_domain_authentication_(verify_domain_authentication), 402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) enable_sending_initial_data_(enable_sending_initial_data), 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_credential_frames_(enable_credential_frames), 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_compression_(enable_compression), 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_ping_based_connection_checking_( 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enable_ping_based_connection_checking), 407558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch protocol_(default_protocol), 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) credential_state_(SpdyCredentialState::kDefaultNumSlots), 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_at_risk_of_loss_time_( 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)), 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hung_interval_( 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kHungIntervalSeconds)), 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trusted_spdy_proxy_(trusted_spdy_proxy), 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) time_func_(time_func) { 415558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we 416558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // stop supporting SPDY/1. 417558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DCHECK_GE(protocol_, kProtoSPDY2); 418558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DCHECK_LE(protocol_, kProtoSPDYMaximumVersion); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(HttpStreamFactory::spdy_enabled()); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION, 42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_unclaimed_push_stream_sweep_time_ = time_func_() + 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): consider randomization of the stream_hi_water_mark. 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdySession::~SpdySession() { 429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(!pool_); 431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckClosed(); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(akalin): Check connection->is_initialized() instead. This 4347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // requires re-working CreateFakeSpdySession(), though. 4357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(connection_->socket()); 4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // With SPDY we can't recycle sockets. 4377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch connection_->socket()->Disconnect(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordHistograms(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Error SpdySession::InitializeWithSocket( 4457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scoped_ptr<ClientSocketHandle> connection, 446ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdySessionPool* pool, 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_secure, 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int certificate_error_code) { 449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(availability_state_, STATE_AVAILABLE); 451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(read_state_, READ_STATE_DO_READ); 452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(write_state_, WRITE_STATE_IDLE); 4537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(!connection_); 454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(certificate_error_code == OK || 456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch certificate_error_code < ERR_IO_PENDING); 4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(akalin): Check connection->is_initialized() instead. This 4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // requires re-working CreateFakeSpdySession(), though. 4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(connection->socket()); 460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter spdy_sessions("spdy.sessions"); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_sessions.Increment(); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch connection_ = connection.Pass(); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_secure_ = is_secure; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certificate_error_code_ = certificate_error_code; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NextProto protocol_negotiated = 4697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch connection_->socket()->GetNegotiatedProtocol(); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (protocol_negotiated != kProtoUnknown) { 471558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch protocol_ = protocol_negotiated; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 473558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we 474558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // stop supporting SPDY/1. 475558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DCHECK_GE(protocol_, kProtoSPDY2); 476558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DCHECK_LE(protocol_, kProtoSPDYMaximumVersion); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocket* ssl_socket = GetSSLClientSocket(); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_socket && ssl_socket->WasChannelIDSent()) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // According to the SPDY spec, the credential associated with the TLS 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // connection is stored in slot[1]. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) credential_state_.SetHasCredential(GURL("https://" + 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_port_pair().ToString())); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (protocol_ == kProtoHTTP2Draft04) 487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) send_connection_header_prefix_ = true; 488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 489558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (protocol_ >= kProtoSPDY31) { 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flow_control_state_ = FLOW_CONTROL_STREAM_AND_SESSION; 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_send_window_size_ = kSpdySessionInitialWindowSize; 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_recv_window_size_ = kSpdySessionInitialWindowSize; 493558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } else if (protocol_ >= kProtoSPDY3) { 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flow_control_state_ = FLOW_CONTROL_STREAM; 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flow_control_state_ = FLOW_CONTROL_NONE; 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffered_spdy_framer_.reset( 500558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch new BufferedSpdyFramer(NextProtoToSpdyMajorVersion(protocol_), 501558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch enable_compression_)); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_spdy_framer_->set_visitor(this); 5037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch buffered_spdy_framer_->set_debug_visitor(this); 504558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch UMA_HISTOGRAM_ENUMERATION("Net.SpdyVersion", protocol_, kProtoMaximumVersion); 5057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(SPDY_PROXY_AUTH_ORIGIN) 5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_BOOLEAN("Net.SpdySessions_DataReductionProxy", 5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host_port_pair().Equals(HostPortPair::FromURL( 5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GURL(SPDY_PROXY_AUTH_ORIGIN)))); 5097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log_.AddEvent( 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_INITIALIZED, 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) connection_->socket()->NetLog().source().ToEventParametersCallback()); 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int error = DoReadLoop(READ_STATE_DO_READ, OK); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error == ERR_IO_PENDING) 5177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch error = OK; 5187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (error == OK) { 519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) connection_->AddHigherLayeredPool(this); 521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (enable_sending_initial_data_) 522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SendInitialData(); 523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pool_ = pool; 524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckClosed(); 5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return static_cast<Error>(error); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!verify_domain_authentication_) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLInfo ssl_info; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_npn_negotiated; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NextProto protocol_negotiated = kProtoUnknown; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // This is not a secure session, so all domains are okay. 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !ssl_info.client_cert_sent && 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (enable_credential_frames_ || !ssl_info.channel_id_sent || 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServerBoundCertService::GetDomainForHost(domain) == 54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ServerBoundCertService::GetDomainForHost(host_port_pair().host())) && 54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ssl_info.cert->VerifyNameMatch(domain); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdySession::GetPushStream( 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 552a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream>* stream, 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& stream_net_log) { 554ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 556a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream->reset(); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // TODO(akalin): Add unit test exercising this code path. 559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_CONNECTION_CLOSED; 561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Error err = TryAccessStream(url); 563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (err != OK) 564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return err; 565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *stream = GetActivePushStream(url); 567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (*stream) { 568ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(streams_pushed_and_claimed_count_, streams_pushed_count_); 569ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch streams_pushed_and_claimed_count_++; 570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return OK; 572ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 573ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 574bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// {,Try}CreateStream() and TryAccessStream() can be called with 575bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// |in_io_loop_| set if a stream is being created in response to 576bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// another being closed due to received data. 577bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochError SpdySession::TryAccessStream(const GURL& url) { 579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 580ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_secure_ && certificate_error_code_ != OK && 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (url.SchemeIs("https") || url.SchemeIs("wss"))) { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordProtocolErrorHistogram( 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION); 585ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = DoCloseSession( 586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<Error>(certificate_error_code_), 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Tried to get SPDY stream for secure content over an unauthenticated " 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "session."); 589ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, SESSION_CLOSED_AND_REMOVED); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SPDY_PROTOCOL_ERROR; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)int SpdySession::TryCreateStream( 5963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::WeakPtr<SpdyStreamRequest>& request, 5973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::WeakPtr<SpdyStream>* stream) { 5983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(request); 599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 600ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_GOING_AWAY) 601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_FAILED; 602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // TODO(akalin): Add unit test exercising this code path. 604ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 605ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_CONNECTION_CLOSED; 606ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Error err = TryAccessStream(request->url()); 608ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (err != OK) 609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return err; 6107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!max_concurrent_streams_ || 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (active_streams_.size() + created_streams_.size() < 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_concurrent_streams_)) { 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CreateStream(*request, stream); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stalled_streams_++; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS); 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_create_stream_queues_[request->priority()].push_back(request); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SpdySession::CreateStream(const SpdyStreamRequest& request, 624a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream>* stream) { 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GE(request.priority(), MINIMUM_PRIORITY); 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LT(request.priority(), NUM_PRIORITIES); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_GOING_AWAY) 629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_FAILED; 630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 631ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // TODO(akalin): Add unit test exercising this code path. 632ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 633ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_CONNECTION_CLOSED; 634ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Error err = TryAccessStream(request.url()); 636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (err != OK) { 637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // This should have been caught in TryCreateStream(). 638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NOTREACHED(); 639ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return err; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(connection_->socket()); 643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(connection_->socket()->IsConnected()); 644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (connection_->socket()) { 645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Net.SpdySession.CreateStreamWithSocketConnected", 646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) connection_->socket()->IsConnected()); 647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!connection_->socket()->IsConnected()) { 648ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = DoCloseSession( 649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ERR_CONNECTION_CLOSED, 650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "Tried to create SPDY stream for a closed socket connection."); 651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, SESSION_CLOSED_AND_REMOVED); 652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ERR_CONNECTION_CLOSED; 653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 656a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) scoped_ptr<SpdyStream> new_stream( 657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new SpdyStream(request.type(), GetWeakPtr(), request.url(), 658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch request.priority(), 659a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream_initial_send_window_size_, 660a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream_initial_recv_window_size_, 66190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) request.net_log())); 662a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) *stream = new_stream->GetWeakPtr(); 663a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) InsertCreatedStream(new_stream.Pass()); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS( 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Net.SpdyPriorityCount", 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<int>(request.priority()), 0, 10, 11); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void SpdySession::CancelStreamRequest( 6733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::WeakPtr<SpdyStreamRequest>& request) { 6743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(request); 6757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (DCHECK_IS_ON()) { 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |request| should not be in a queue not matching its priority. 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < NUM_PRIORITIES; ++i) { 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (request->priority() == i) 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PendingStreamRequestQueue* queue = &pending_create_stream_queues_[i]; 6823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(std::find_if(queue->begin(), 6833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) queue->end(), 6843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RequestEquals(request)) == queue->end()); 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PendingStreamRequestQueue* queue = 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &pending_create_stream_queues_[request->priority()]; 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove |request| from |queue| while preserving the order of the 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // other elements. 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PendingStreamRequestQueue::iterator it = 6933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::find_if(queue->begin(), queue->end(), RequestEquals(request)); 6943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // The request may already be removed if there's a 6953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // CompleteStreamRequest() in flight. 6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != queue->end()) { 6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it = queue->erase(it); 6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |request| should be in the queue at most once, and if it is 6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // present, should not be pending completion. 7003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(std::find_if(it, queue->end(), RequestEquals(request)) == 7013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) queue->end()); 7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 7043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)base::WeakPtr<SpdyStreamRequest> SpdySession::GetNextPendingStreamRequest() { 7063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (int j = NUM_PRIORITIES - 1; j >= MINIMUM_PRIORITY; --j) { 7073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (pending_create_stream_queues_[j].empty()) 7083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) continue; 7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::WeakPtr<SpdyStreamRequest> pending_request = 7113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pending_create_stream_queues_[j].front(); 7123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(pending_request); 7133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pending_create_stream_queues_[j].pop_front(); 7143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return pending_request; 7153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 7163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return base::WeakPtr<SpdyStreamRequest>(); 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdySession::ProcessPendingStreamRequests() { 720a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Like |max_concurrent_streams_|, 0 means infinite for 721a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // |max_requests_to_process|. 722a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) size_t max_requests_to_process = 0; 723a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (max_concurrent_streams_ != 0) { 724a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) max_requests_to_process = 725a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) max_concurrent_streams_ - 726a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (active_streams_.size() + created_streams_.size()); 727a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 728a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (size_t i = 0; 729a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) max_requests_to_process == 0 || i < max_requests_to_process; ++i) { 7303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::WeakPtr<SpdyStreamRequest> pending_request = 7313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetNextPendingStreamRequest(); 7323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!pending_request) 733a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) break; 7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 7353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::MessageLoop::current()->PostTask( 7363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FROM_HERE, 7373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Bind(&SpdySession::CompleteStreamRequest, 7383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) weak_factory_.GetWeakPtr(), 7393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pending_request)); 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySession::NeedsCredentials() const { 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_secure_) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocket* ssl_socket = GetSSLClientSocket(); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ssl_socket->WasChannelIDSent(); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SpdySession::AddPooledAlias(const SpdySessionKey& alias_key) { 75390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pooled_aliases_.insert(alias_key); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdySession::GetProtocolVersion() const { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffered_spdy_framer_->protocol_version(); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbase::WeakPtr<SpdySession> SpdySession::GetWeakPtr() { 762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return weak_factory_.GetWeakPtr(); 763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 765a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool SpdySession::CloseOneIdleConnection() { 766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(pool_); 769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!active_streams_.empty()) 770a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return false; 771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = 772ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(ERR_CONNECTION_CLOSED, "Closing one idle connection."); 773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (result != SESSION_CLOSED_AND_REMOVED) { 774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NOTREACHED(); 775ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 776ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 777ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return true; 778a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 779a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::EnqueueStreamWrite( 781a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const base::WeakPtr<SpdyStream>& stream, 782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyFrameType frame_type, 783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyBufferProducer> producer) { 784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(frame_type == HEADERS || 785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_type == DATA || 786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_type == CREDENTIAL || 787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_type == SYN_STREAM); 788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnqueueWrite(stream->priority(), frame_type, producer.Pass(), stream); 789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<SpdyFrame> SpdySession::CreateSynStream( 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId stream_id, 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestPriority priority, 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 credential_slot, 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyControlFlags flags, 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& headers) { 797a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 798a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CHECK(it != active_streams_.end()); 799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(it->second.stream->stream_id(), stream_id); 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendPrefacePingIfNoneInFlight(); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> syn_frame( 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_spdy_framer_->CreateSynStream( 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, 0, 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credential_slot, flags, enable_compression_, &headers)); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter spdy_requests("spdy.requests"); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_requests.Increment(); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_initiated_count_++; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log().IsLoggingAllEvents()) { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_SYN_STREAM, 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdySynCallback, &headers, 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (flags & CONTROL_FLAG_FIN) != 0, 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, 0)); 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return syn_frame.Pass(); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SpdySession::CreateCredentialFrame( 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& origin, 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& key, 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& cert, 830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RequestPriority priority, 831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyFrame>* credential_frame) { 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(is_secure_); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocket* ssl_socket = GetSSLClientSocket(); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ssl_socket); 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ssl_socket->WasChannelIDSent()); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyCredential credential; 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string tls_unique; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_socket->GetTLSUniqueChannelBinding(&tls_unique); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t slot = credential_state_.SetHasCredential(GURL(origin)); 841bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int rv = SpdyCredentialBuilder::Build(tls_unique, key, cert, slot, 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &credential); 843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return rv; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) credential_frame->reset( 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_spdy_framer_->CreateCredentialFrame(credential)); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log().IsLoggingAllEvents()) { 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL, 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin)); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return OK; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id, 860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IOBuffer* data, 861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int len, 862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyDataFlags flags) { 863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) { 864ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NOTREACHED(); 865ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return scoped_ptr<SpdyBuffer>(); 866ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 867ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 868a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 869a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CHECK(it != active_streams_.end()); 870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStream* stream = it->second.stream; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(stream->stream_id(), stream_id); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (len < 0) { 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return scoped_ptr<SpdyBuffer>(); 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int effective_len = std::min(len, kMaxSpdyFrameChunkSize); 879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool send_stalled_by_stream = 881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (flow_control_state_ >= FLOW_CONTROL_STREAM) && 882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (stream->send_window_size() <= 0); 883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool send_stalled_by_session = IsSendStalled(); 884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // NOTE: There's an enum of the same name in histograms.xml. 886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) enum SpdyFrameFlowControlState { 887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SEND_NOT_STALLED, 888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SEND_STALLED_BY_STREAM, 889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SEND_STALLED_BY_SESSION, 890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SEND_STALLED_BY_STREAM_AND_SESSION, 891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyFrameFlowControlState frame_flow_control_state = SEND_NOT_STALLED; 894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (send_stalled_by_stream) { 895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (send_stalled_by_session) { 896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_flow_control_state = SEND_STALLED_BY_STREAM_AND_SESSION; 897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_flow_control_state = SEND_STALLED_BY_STREAM; 899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (send_stalled_by_session) { 901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_flow_control_state = SEND_STALLED_BY_SESSION; 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (flow_control_state_ == FLOW_CONTROL_STREAM) { 905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION( 906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "Net.SpdyFrameStreamFlowControlState", 907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_flow_control_state, 908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SEND_STALLED_BY_STREAM + 1); 909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION( 911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "Net.SpdyFrameStreamAndSessionFlowControlState", 912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_flow_control_state, 913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SEND_STALLED_BY_STREAM_AND_SESSION + 1); 914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Obey send window size of the stream if stream flow control is 917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // enabled. 9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (flow_control_state_ >= FLOW_CONTROL_STREAM) { 919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (send_stalled_by_stream) { 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->set_send_stalled_by_flow_control(true); 921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Even though we're currently stalled only by the stream, we 922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // might end up being stalled by the session also. 923a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) QueueSendStalledStream(*stream); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_BY_STREAM_SEND_WINDOW, 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("stream_id", stream_id)); 927c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return scoped_ptr<SpdyBuffer>(); 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) effective_len = std::min(effective_len, stream->send_window_size()); 931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 932c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Obey send window size of the session if session flow control is 934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // enabled. 935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (send_stalled_by_session) { 937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->set_send_stalled_by_flow_control(true); 938a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) QueueSendStalledStream(*stream); 939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log().AddEvent( 940c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_BY_SESSION_SEND_WINDOW, 941c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::IntegerCallback("stream_id", stream_id)); 942c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return scoped_ptr<SpdyBuffer>(); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 944c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 945c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) effective_len = std::min(effective_len, session_send_window_size_); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 948c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(effective_len, 0); 949c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 950c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clear FIN flag if only some of the data will be in the data 951c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // frame. 952c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (effective_len < len) 953c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); 954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log().IsLoggingAllEvents()) { 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_SEND_DATA, 958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&NetLogSpdyDataCallback, stream_id, effective_len, 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (flags & DATA_FLAG_FIN) != 0)); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send PrefacePing for DATA_FRAMEs with nonzero payload size. 963c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (effective_len > 0) 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendPrefacePingIfNoneInFlight(); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): reduce memory copies here. 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> frame( 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_spdy_framer_->CreateDataFrame( 970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream_id, data->data(), 971c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<uint32>(effective_len), flags)); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyBuffer> data_buffer(new SpdyBuffer(frame.Pass())); 974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DecreaseSendWindowSize(static_cast<int32>(effective_len)); 977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_buffer->AddConsumeCallback( 978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&SpdySession::OnWriteBufferConsumed, 979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr(), 980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<size_t>(effective_len))); 981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 983c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return data_buffer.Pass(); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 986a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdySession::CloseActiveStream(SpdyStreamId stream_id, int status) { 987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_NE(stream_id, 0u); 988a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 989a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::iterator it = active_streams_.find(stream_id); 990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it == active_streams_.end()) { 991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 992a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 994a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CloseActiveStreamIterator(it, status); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 998a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdySession::CloseCreatedStream( 999a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const base::WeakPtr<SpdyStream>& stream, int status) { 1000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_EQ(stream->stream_id(), 0u); 1001a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreatedStreamSet::iterator it = created_streams_.find(stream.get()); 1003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it == created_streams_.end()) { 1004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 1005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 1006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1007a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CloseCreatedStreamIterator(it, status); 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::ResetStream(SpdyStreamId stream_id, 10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyRstStreamStatus status, 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& description) { 1014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_NE(stream_id, 0u); 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ActiveStreamMap::iterator it = active_streams_.find(stream_id); 1017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it == active_streams_.end()) { 1018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 1019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 1020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResetStreamIterator(it, status, description); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ContainsKey(active_streams_, stream_id); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState SpdySession::GetLoadState() const { 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just report that we're idle since the session could be doing 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // many things concurrently. 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LOAD_STATE_IDLE; 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SpdySession::CloseActiveStreamIterator(ActiveStreamMap::iterator it, 1036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int status) { 1037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(mbelshe): We should send a RST_STREAM control frame here 1038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // so that the server can cancel a large send. 1039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyStream> owned_stream(it->second.stream); 1041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch active_streams_.erase(it); 1042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1043ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // TODO(akalin): When SpdyStream was ref-counted (and 1044ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // |unclaimed_pushed_streams_| held scoped_refptr<SpdyStream>), this 1045ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // was only done when status was not OK. This meant that pushed 1046ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // streams can still be claimed after they're closed. This is 1047ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // probably something that we still want to support, although server 1048ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // push is hardly used. Write tests for this and fix this. (See 1049ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // http://crbug.com/261712 .) 1050ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (owned_stream->type() == SPDY_PUSH_STREAM) 10513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) unclaimed_pushed_streams_.erase(owned_stream->url()); 10523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::WeakPtr<SpdySession> weak_this = GetWeakPtr(); 1054ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeleteStream(owned_stream.Pass(), status); 10563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!weak_this) 10583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 10593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (availability_state_ == STATE_CLOSED) 10613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 10623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 10633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // If there are no active streams and the socket pool is stalled, close the 10643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // session to free up a socket slot. 10653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (active_streams_.empty() && connection_->IsPoolStalled()) { 10663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CloseSessionResult result = 10673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DoCloseSession(ERR_CONNECTION_CLOSED, "Closing idle connection."); 10683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK_NE(result, SESSION_ALREADY_CLOSED); 10693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SpdySession::CloseCreatedStreamIterator(CreatedStreamSet::iterator it, 1073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int status) { 1074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyStream> owned_stream(*it); 1075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch created_streams_.erase(it); 1076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeleteStream(owned_stream.Pass(), status); 1077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid SpdySession::ResetStreamIterator(ActiveStreamMap::iterator it, 1080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyRstStreamStatus status, 1081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& description) { 1082bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Send the RST_STREAM frame first as CloseActiveStreamIterator() 1083bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // may close us. 1084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStreamId stream_id = it->first; 1085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RequestPriority priority = it->second.stream->priority(); 1086bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame(stream_id, priority, status, description); 1087bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 1088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Removes any pending writes for the stream except for possibly an 1089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // in-flight one. 1090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); 1091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1093bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id, 1094bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch RequestPriority priority, 1095bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch SpdyRstStreamStatus status, 1096bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch const std::string& description) { 1097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_NE(stream_id, 0u); 1098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1099eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch net_log().AddEvent( 1100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, 1101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); 1102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(buffered_spdy_framer_.get()); 1104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> rst_frame( 1105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch buffered_spdy_framer_->CreateRstStream(stream_id, status)); 1106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EnqueueSessionWrite(priority, RST_STREAM, rst_frame.Pass()); 1108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordProtocolErrorHistogram( 1109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); 1110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::PumpReadLoop(ReadState expected_read_state, int result) { 1113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 1114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 1115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(read_state_, expected_read_state); 1116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch result = DoReadLoop(expected_read_state, result); 1118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) { 1120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, error_on_close_); 1121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(error_on_close_, ERR_IO_PENDING); 1122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch RemoveFromPool(); 1123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(result == OK || result == ERR_IO_PENDING); 11279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochint SpdySession::DoReadLoop(ReadState expected_read_state, int result) { 1130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 1131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 1132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(read_state_, expected_read_state); 11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_io_loop_ = true; 11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int bytes_read_without_yielding = 0; 1137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Loop until the session is closed, the read becomes blocked, or 1139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // the read limit is exceeded. 1140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while (true) { 1141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch (read_state_) { 1142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case READ_STATE_DO_READ: 11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(result, OK); 11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result = DoRead(); 11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case READ_STATE_DO_READ_COMPLETE: 1147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (result > 0) 1148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bytes_read_without_yielding += result; 11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result = DoReadComplete(result); 11502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 1152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NOTREACHED() << "read_state_: " << read_state_; 11532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 11542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) { 1157ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, error_on_close_); 1158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(result, ERR_IO_PENDING); 1159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (result == ERR_IO_PENDING) 1163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (bytes_read_without_yielding > kMaxReadBytesWithoutYielding) { 1166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch read_state_ = READ_STATE_DO_READ; 1167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MessageLoop::current()->PostTask( 1168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch FROM_HERE, 1169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&SpdySession::PumpReadLoop, 1170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch weak_factory_.GetWeakPtr(), READ_STATE_DO_READ, OK)); 1171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch result = ERR_IO_PENDING; 1172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_io_loop_ = false; 11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return result; 11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SpdySession::DoRead() { 1183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1184ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 11852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CHECK(connection_); 11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(connection_->socket()); 1188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch read_state_ = READ_STATE_DO_READ_COMPLETE; 11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connection_->socket()->Read( 11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) read_buffer_.get(), 11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kReadBufferSize, 1192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&SpdySession::PumpReadLoop, 1193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch weak_factory_.GetWeakPtr(), READ_STATE_DO_READ_COMPLETE)); 11942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int SpdySession::DoReadComplete(int result) { 1197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 1199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse a frame. For now this code requires that the frame fit into our 1201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // buffer (kReadBufferSize). 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): support arbitrarily large frames! 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (result == 0) { 1205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.EOF", 1206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch total_bytes_received_, 1, 100000000, 50); 1207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult close_session_result = 1208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(ERR_CONNECTION_CLOSED, "Connection closed"); 1209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(close_session_result, SESSION_CLOSED_BUT_NOT_REMOVED); 1210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(availability_state_, STATE_CLOSED); 1211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(error_on_close_, ERR_CONNECTION_CLOSED); 12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_CONNECTION_CLOSED; 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (result < 0) { 1216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult close_session_result = 1217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(static_cast<Error>(result), "result is < 0."); 1218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(close_session_result, SESSION_CLOSED_BUT_NOT_REMOVED); 1219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(availability_state_, STATE_CLOSED); 1220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(error_on_close_, result); 1221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return result; 1222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 12242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) total_bytes_received_ += result; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch last_activity_time_ = time_func_(); 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 12292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char* data = read_buffer_->data(); 1230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while (result > 0) { 1231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint32 bytes_processed = buffered_spdy_framer_->ProcessInput(data, result); 12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) result -= bytes_processed; 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_processed; 1234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) { 1236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(error_on_close_, ERR_IO_PENDING); 1237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return error_on_close_; 1238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 12399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(buffered_spdy_framer_->error_code(), SpdyFramer::SPDY_NO_ERROR); 1241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch read_state_ = READ_STATE_DO_READ; 12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return OK; 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::PumpWriteLoop(WriteState expected_write_state, int result) { 1248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 1249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 1250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(write_state_, expected_write_state); 1251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch result = DoWriteLoop(expected_write_state, result); 1253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) { 1255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, error_on_close_); 1256ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(error_on_close_, ERR_IO_PENDING); 1257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch RemoveFromPool(); 1258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(result == OK || result == ERR_IO_PENDING); 1262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1263ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1264ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochint SpdySession::DoWriteLoop(WriteState expected_write_state, int result) { 1265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 1266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 1267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(write_state_, WRITE_STATE_IDLE); 1268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(write_state_, expected_write_state); 1269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_io_loop_ = true; 1271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Loop until the session is closed or the write becomes blocked. 1273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while (true) { 1274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch (write_state_) { 1275ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case WRITE_STATE_DO_WRITE: 1276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, OK); 1277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch result = DoWrite(); 1278ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1279ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case WRITE_STATE_DO_WRITE_COMPLETE: 1280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch result = DoWriteComplete(result); 1281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case WRITE_STATE_IDLE: 1283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch default: 1284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NOTREACHED() << "write_state_: " << write_state_; 1285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) { 1289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, error_on_close_); 1290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(result, ERR_IO_PENDING); 1291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (write_state_ == WRITE_STATE_IDLE) { 1295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, ERR_IO_PENDING); 1296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (result == ERR_IO_PENDING) 1300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_io_loop_ = false; 1305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return result; 1307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochint SpdySession::DoWrite() { 1310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 1312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(buffered_spdy_framer_); 1314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (in_flight_write_) { 1315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_GT(in_flight_write_->GetRemainingSize(), 0u); 1316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 1317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Grab the next frame to send. 1318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyFrameType frame_type = DATA; 1319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyBufferProducer> producer; 1320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdyStream> stream; 1321ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!write_queue_.Dequeue(&frame_type, &producer, &stream)) { 1322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch write_state_ = WRITE_STATE_IDLE; 1323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_IO_PENDING; 1324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (stream.get()) 1327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(!stream->IsClosed()); 1328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Activate the stream only when sending the SYN_STREAM frame to 1330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // guarantee monotonically-increasing stream IDs. 1331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (frame_type == SYN_STREAM) { 1332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (stream.get() && stream->stream_id() == 0) { 1333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<SpdyStream> owned_stream = 1334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ActivateCreatedStream(stream.get()); 1335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch InsertActivatedStream(owned_stream.Pass()); 1336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 1337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NOTREACHED(); 1338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_UNEXPECTED; 1339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_flight_write_ = producer->ProduceBuffer(); 1343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!in_flight_write_) { 1344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NOTREACHED(); 1345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return ERR_UNEXPECTED; 1346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1347ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_flight_write_frame_type_ = frame_type; 1348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_flight_write_frame_size_ = in_flight_write_->GetRemainingSize(); 1349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_GE(in_flight_write_frame_size_, 1350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch buffered_spdy_framer_->GetFrameMinimumSize()); 1351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_flight_write_stream_ = stream; 1352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch write_state_ = WRITE_STATE_DO_WRITE_COMPLETE; 1355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Explicitly store in a scoped_refptr<IOBuffer> to avoid problems 1357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // with Socket implementations that don't store their IOBuffer 1358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // argument in a scoped_refptr<IOBuffer> (see crbug.com/232345). 1359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_refptr<IOBuffer> write_io_buffer = 1360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_flight_write_->GetIOBufferForRemainingData(); 1361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return connection_->socket()->Write( 1362ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch write_io_buffer.get(), 1363ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch in_flight_write_->GetRemainingSize(), 1364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&SpdySession::PumpWriteLoop, 1365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch weak_factory_.GetWeakPtr(), WRITE_STATE_DO_WRITE_COMPLETE)); 1366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochint SpdySession::DoWriteComplete(int result) { 1369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 1371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(result, ERR_IO_PENDING); 1372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(in_flight_write_->GetRemainingSize(), 0u); 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch last_activity_time_ = time_func_(); 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result < 0) { 1377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(result, ERR_IO_PENDING); 1378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_.reset(); 1379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_type_ = DATA; 1380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_size_ = 0; 1381a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) in_flight_write_stream_.reset(); 1382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult close_session_result = 1383ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(static_cast<Error>(result), "Write error"); 1384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(close_session_result, SESSION_CLOSED_BUT_NOT_REMOVED); 1385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(availability_state_, STATE_CLOSED); 1386ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(error_on_close_, result); 1387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return result; 1388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It should not be possible to have written more bytes than our 1391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // in_flight_write_. 1392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(static_cast<size_t>(result), 1393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_->GetRemainingSize()); 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result > 0) { 1396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_->Consume(static_cast<size_t>(result)); 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only notify the stream when we've fully written the pending frame. 1399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (in_flight_write_->GetRemainingSize() == 0) { 1400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It is possible that the stream was cancelled while we were 1401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // writing to the socket. 1402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (in_flight_write_stream_.get()) { 1403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(in_flight_write_frame_size_, 0u); 1404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_stream_->OnFrameWriteComplete( 1405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_type_, 1406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_size_); 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cleanup the write which just completed. 1410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_.reset(); 1411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_type_ = DATA; 1412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) in_flight_write_frame_size_ = 0; 1413a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) in_flight_write_stream_.reset(); 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch write_state_ = WRITE_STATE_DO_WRITE; 1418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return OK; 14199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 14209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::DcheckGoingAway() const { 1422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_GE(availability_state_, STATE_GOING_AWAY); 1423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (DCHECK_IS_ON()) { 1424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (int i = 0; i < NUM_PRIORITIES; ++i) { 1425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(pending_create_stream_queues_[i].empty()); 14269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 14279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 1428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(created_streams_.empty()); 1429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::DcheckClosed() const { 1432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckGoingAway(); 1433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(availability_state_, STATE_CLOSED); 1434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(error_on_close_, ERR_IO_PENDING); 1435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(active_streams_.empty()); 1436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(unclaimed_pushed_streams_.empty()); 1437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(write_queue_.IsEmpty()); 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::StartGoingAway(SpdyStreamId last_good_stream_id, 1441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Error status) { 1442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_GE(availability_state_, STATE_GOING_AWAY); 1443bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 1444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // The loops below are carefully written to avoid reentrancy problems. 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) while (true) { 14473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t old_size = GetTotalSize(pending_create_stream_queues_); 14483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::WeakPtr<SpdyStreamRequest> pending_request = 14493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) GetNextPendingStreamRequest(); 14503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!pending_request) 14513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) break; 14523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // No new stream requests should be added while the session is 14533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // going away. 14543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK_GT(old_size, GetTotalSize(pending_create_stream_queues_)); 14553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pending_request->OnRequestCompleteFailure(ERR_ABORTED); 1456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 14577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 14587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) while (true) { 14593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t old_size = active_streams_.size(); 14607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ActiveStreamMap::iterator it = 14617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) active_streams_.lower_bound(last_good_stream_id + 1); 14627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (it == active_streams_.end()) 14637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) break; 1464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LogAbandonedActiveStream(it, status); 1465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CloseActiveStreamIterator(it, status); 14663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // No new streams should be activated while the session is going 14673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // away. 14683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK_GT(old_size, active_streams_.size()); 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!created_streams_.empty()) { 14723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t old_size = created_streams_.size(); 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreatedStreamSet::iterator it = created_streams_.begin(); 1474a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LogAbandonedStream(*it, status); 1475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CloseCreatedStreamIterator(it, status); 14763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // No new streams should be created while the session is going 14773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // away. 14783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK_GT(old_size, created_streams_.size()); 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_queue_.RemovePendingWritesForStreamsAfter(last_good_stream_id); 1482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckGoingAway(); 1484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::MaybeFinishGoingAway() { 1487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckGoingAway(); 1488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (active_streams_.empty() && availability_state_ != STATE_CLOSED) { 1489ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = 1490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(ERR_CONNECTION_CLOSED, "Finished going away"); 1491ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(result, SESSION_ALREADY_CLOSED); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdySession::CloseSessionResult SpdySession::DoCloseSession( 1496ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Error err, 1497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const std::string& description) { 1498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LT(err, ERR_IO_PENDING); 1499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1500ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return SESSION_ALREADY_CLOSED; 1502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch net_log_.AddEvent( 1504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NetLog::TYPE_SPDY_SESSION_CLOSE, 1505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&NetLogSpdySessionCloseCallback, err, &description)); 1506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SpdySession.ClosedOnError", -err); 1508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.OtherErrors", 1509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch total_bytes_received_, 1, 100000000, 50); 1510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // |pool_| will be NULL when |InitializeWithSocket()| is in the 1512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // call stack. 1513ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (pool_ && availability_state_ != STATE_GOING_AWAY) 1514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pool_->MakeSessionUnavailable(GetWeakPtr()); 1515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch availability_state_ = STATE_CLOSED; 1517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch error_on_close_ = err; 1518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch StartGoingAway(0, err); 1520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_queue_.Clear(); 1521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckClosed(); 1523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (in_io_loop_) 1525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return SESSION_CLOSED_BUT_NOT_REMOVED; 1526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1527ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch RemoveFromPool(); 1528ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return SESSION_CLOSED_AND_REMOVED; 1529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::RemoveFromPool() { 1532ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckClosed(); 1533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(pool_); 1534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdySessionPool* pool = pool_; 1536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pool_ = NULL; 1537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pool->RemoveUnavailableSession(GetWeakPtr()); 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1540a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdySession::LogAbandonedStream(SpdyStream* stream, Error status) { 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(stream); 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string description = base::StringPrintf( 1543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch "ABANDONED (stream_id=%d): ", stream->stream_id()) + 1544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch stream->url().spec(); 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->LogStreamError(status, description); 1546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We don't increment the streams abandoned counter here. If the 1547ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // stream isn't active (i.e., it hasn't written anything to the wire 1548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // yet) then it's as if it never existed. If it is active, then 1549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // LogAbandonedActiveStream() will increment the counters. 1550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1551ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1552ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it, 1553ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Error status) { 1554ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_GT(it->first, 0u); 1555ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LogAbandonedStream(it->second.stream, status); 1556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ++streams_abandoned_count_; 1557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::StatsCounter abandoned_streams("spdy.abandoned_streams"); 1558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch abandoned_streams.Increment(); 1559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (it->second.stream->type() == SPDY_PUSH_STREAM && 1560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unclaimed_pushed_streams_.find(it->second.stream->url()) != 1561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unclaimed_pushed_streams_.end()) { 1562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::StatsCounter abandoned_push_streams("spdy.abandoned_push_streams"); 1563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch abandoned_push_streams.Increment(); 1564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdySession::GetNewStreamId() { 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id = stream_hi_water_mark_; 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_hi_water_mark_ += 2; 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_hi_water_mark_ > 0x7fff) 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_hi_water_mark_ = 1; 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return id; 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::CloseSessionOnError(Error err, 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& description) { 1577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We may be called from anywhere, so we can't expect a particular 1578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // return value. 1579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ignore_result(DoCloseSession(err, description)); 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* SpdySession::GetInfoAsValue() const { 15832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::DictionaryValue* dict = new base::DictionaryValue(); 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("source_id", net_log_.source().id); 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 158790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) dict->SetString("host_port_pair", host_port_pair().ToString()); 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pooled_aliases_.empty()) { 15892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ListValue* alias_list = new base::ListValue(); 159090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (std::set<SpdySessionKey>::const_iterator it = 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pooled_aliases_.begin(); 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != pooled_aliases_.end(); it++) { 159390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) alias_list->Append(new base::StringValue( 159490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) it->host_port_pair().ToString())); 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->Set("aliases", alias_list); 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 159890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) dict->SetString("proxy", host_port_proxy_pair().second.ToURI()); 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("active_streams", active_streams_.size()); 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("unclaimed_pushed_streams", 1603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unclaimed_pushed_streams_.size()); 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetBoolean("is_secure", is_secure_); 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetString("protocol_negotiated", 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocket::NextProtoToString( 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->socket()->GetNegotiatedProtocol())); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dict->SetInteger("error", error_on_close_); 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("max_concurrent_streams", max_concurrent_streams_); 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("streams_initiated_count", streams_initiated_count_); 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("streams_pushed_count", streams_pushed_count_); 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("streams_pushed_and_claimed_count", 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_pushed_and_claimed_count_); 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("streams_abandoned_count", streams_abandoned_count_); 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetInteger("frames_received", buffered_spdy_framer_->frames_received()); 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetBoolean("sent_settings", sent_settings_); 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dict->SetBoolean("received_settings", received_settings_); 16242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dict->SetInteger("send_window_size", session_send_window_size_); 16262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dict->SetInteger("recv_window_size", session_recv_window_size_); 16272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dict->SetInteger("unacked_recv_window_bytes", 16282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_unacked_recv_window_bytes_); 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dict; 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySession::IsReused() const { 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffered_spdy_framer_->frames_received() > 0; 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SpdySession::GetLoadTimingInfo(SpdyStreamId stream_id, 16372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadTimingInfo* load_timing_info) const { 16382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return connection_->GetLoadTimingInfo(stream_id != kFirstStreamId, 16392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) load_timing_info); 16402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 16412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdySession::GetPeerAddress(IPEndPoint* address) const { 1643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = ERR_SOCKET_NOT_CONNECTED; 1644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (connection_->socket()) { 1645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rv = connection_->socket()->GetPeerAddress(address); 16462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Net.SpdySessionSocketNotConnectedGetPeerAddress", 1649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rv == ERR_SOCKET_NOT_CONNECTED); 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return rv; 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SpdySession::GetLocalAddress(IPEndPoint* address) const { 1655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int rv = ERR_SOCKET_NOT_CONNECTED; 1656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (connection_->socket()) { 1657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rv = connection_->socket()->GetLocalAddress(address); 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_BOOLEAN("Net.SpdySessionSocketNotConnectedGetLocalAddress", 1661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rv == ERR_SOCKET_NOT_CONNECTED); 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return rv; 1664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::EnqueueSessionWrite(RequestPriority priority, 1667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyFrameType frame_type, 1668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyFrame> frame) { 1669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(frame_type == RST_STREAM || 1670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_type == SETTINGS || 1671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_type == WINDOW_UPDATE || 1672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame_type == PING); 1673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnqueueWrite( 1674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) priority, frame_type, 1675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyBufferProducer>( 1676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new SimpleBufferProducer( 1677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyBuffer>(new SpdyBuffer(frame.Pass())))), 1678a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream>()); 1679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::EnqueueWrite(RequestPriority priority, 1682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyFrameType frame_type, 1683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<SpdyBufferProducer> producer, 1684a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const base::WeakPtr<SpdyStream>& stream) { 1685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1686ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1688ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool was_idle = write_queue_.IsEmpty(); 1689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) write_queue_.Enqueue(priority, frame_type, producer.Pass(), stream); 1690ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (write_state_ == WRITE_STATE_IDLE) { 1691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(was_idle); 1692ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(!in_flight_write_); 1693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch write_state_ = WRITE_STATE_DO_WRITE; 1694ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::MessageLoop::current()->PostTask( 1695ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch FROM_HERE, 1696ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&SpdySession::PumpWriteLoop, 1697ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch weak_factory_.GetWeakPtr(), WRITE_STATE_DO_WRITE, OK)); 1698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1701a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdySession::InsertCreatedStream(scoped_ptr<SpdyStream> stream) { 1702a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK_EQ(stream->stream_id(), 0u); 1703a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(created_streams_.find(stream.get()) == created_streams_.end()); 1704a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) created_streams_.insert(stream.release()); 1705a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1707a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)scoped_ptr<SpdyStream> SpdySession::ActivateCreatedStream(SpdyStream* stream) { 1708a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK_EQ(stream->stream_id(), 0u); 1709a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(created_streams_.find(stream) != created_streams_.end()); 1710a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream->set_stream_id(GetNewStreamId()); 1711a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) scoped_ptr<SpdyStream> owned_stream(stream); 1712a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) created_streams_.erase(stream); 1713a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return owned_stream.Pass(); 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1716a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdySession::InsertActivatedStream(scoped_ptr<SpdyStream> stream) { 1717a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) SpdyStreamId stream_id = stream->stream_id(); 1718a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK_NE(stream_id, 0u); 1719a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) std::pair<ActiveStreamMap::iterator, bool> result = 1720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch active_streams_.insert( 1721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::make_pair(stream_id, ActiveStreamInfo(stream.get()))); 1722a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (result.second) { 1723a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ignore_result(stream.release()); 1724a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 1725a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NOTREACHED(); 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1727a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1729a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdySession::DeleteStream(scoped_ptr<SpdyStream> stream, int status) { 1730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (in_flight_write_stream_.get() == stream.get()) { 1731a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // If we're deleting the stream for the in-flight write, we still 1732a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // need to let the write complete, so we clear 1733a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // |in_flight_write_stream_| and let the write finish on its own 1734a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // without notifying |in_flight_write_stream_|. 1735a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) in_flight_write_stream_.reset(); 1736a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 1737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1738a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) write_queue_.RemovePendingWritesForStream(stream->GetWeakPtr()); 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1740bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // |stream->OnClose()| may end up closing |this|, so detect that. 1741bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::WeakPtr<SpdySession> weak_this = GetWeakPtr(); 1742bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->OnClose(status); 1744a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1745bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (!weak_this) 1746bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch return; 1747bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 1748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch (availability_state_) { 1749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case STATE_AVAILABLE: 1750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ProcessPendingStreamRequests(); 1751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case STATE_GOING_AWAY: 1753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DcheckGoingAway(); 1754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MaybeFinishGoingAway(); 1755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case STATE_CLOSED: 1757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Do nothing. 1758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbase::WeakPtr<SpdyStream> SpdySession::GetActivePushStream(const GURL& url) { 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter used_push_streams("spdy.claimed_push_streams"); 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PushedStreamMap::iterator unclaimed_it = unclaimed_pushed_streams_.find(url); 1766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (unclaimed_it == unclaimed_pushed_streams_.end()) 1767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return base::WeakPtr<SpdyStream>(); 1768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyStreamId stream_id = unclaimed_it->second.stream_id; 1770ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unclaimed_pushed_streams_.erase(unclaimed_it); 1771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1772ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); 1773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (active_it == active_streams_.end()) { 1774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 1775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return base::WeakPtr<SpdyStream>(); 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM); 1779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch used_push_streams.Increment(); 1780ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return active_it->second.stream->GetWeakPtr(); 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySession::GetSSLInfo(SSLInfo* ssl_info, 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* was_npn_negotiated, 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NextProto* protocol_negotiated) { 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *was_npn_negotiated = connection_->socket()->WasNpnNegotiated(); 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *protocol_negotiated = connection_->socket()->GetNegotiatedProtocol(); 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return connection_->socket()->GetSSLInfo(ssl_info); 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySession::GetSSLCertRequestInfo( 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLCertRequestInfo* cert_request_info) { 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_secure_) 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSSLClientSocket()->GetSSLCertRequestInfo(cert_request_info); 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServerBoundCertService* SpdySession::GetServerBoundCertService() const { 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_secure_) 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetSSLClientSocket()->GetServerBoundCertService(); 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnError(SpdyFramer::SpdyError error_code) { 1806ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1807ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1808ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1809ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1810ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordProtocolErrorHistogram( 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<SpdyProtocolErrorDetails>(error_code)); 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string description = base::StringPrintf( 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SPDY_ERROR error_code: %d.", error_code); 1815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = 1816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(ERR_SPDY_PROTOCOL_ERROR, description); 1817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnStreamError(SpdyStreamId stream_id, 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& description) { 1822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1823ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ActiveStreamMap::iterator it = active_streams_.find(stream_id); 1828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it == active_streams_.end()) { 1829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We still want to send a frame to reset the stream even if we 1830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // don't know anything about it. 1831bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame( 1832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream_id, IDLE, RST_STREAM_PROTOCOL_ERROR, description); 1833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 1834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, description); 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnStreamFrameData(SpdyStreamId stream_id, 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len, 18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool fin) { 1843ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1844ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1845ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LT(len, 1u << 24); 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log().IsLoggingAllEvents()) { 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_RECV_DATA, 18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin)); 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Build the buffer as early as possible so that we go through the 1856c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // session flow control checks and update 1857c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // |unacked_recv_window_bytes_| properly even when the stream is 1858c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // inactive (since the other side has still reduced its session send 1859c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // window). 1860c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch scoped_ptr<SpdyBuffer> buffer; 1861c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (data) { 1862c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK_GT(len, 0u); 1863c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch buffer.reset(new SpdyBuffer(data, len)); 1864c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 1865c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 1866c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DecreaseRecvWindowSize(static_cast<int32>(len)); 1867c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch buffer->AddConsumeCallback( 1868c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch base::Bind(&SpdySession::OnReadBufferConsumed, 1869c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch weak_factory_.GetWeakPtr())); 1870c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 1871c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else { 1872c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DCHECK_EQ(len, 0u); 1873c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } 1874c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch 1875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ActiveStreamMap::iterator it = active_streams_.find(stream_id); 1876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // By the time data comes in, the stream may already be inactive. 1878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (it == active_streams_.end()) 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStream* stream = it->second.stream; 1882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(stream->stream_id(), stream_id); 1883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it->second.waiting_for_syn_reply) { 1885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& error = "Data received before SYN_REPLY."; 1886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); 1887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); 1888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 1889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->OnDataReceived(buffer.Pass()); 1892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::OnSettings(bool clear_persisted) { 1895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1896ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1899ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (clear_persisted) 1901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) http_server_properties_->ClearSpdySettings(host_port_pair()); 1902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (net_log_.IsLoggingAllEvents()) { 1904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log_.AddEvent( 1905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_RECV_SETTINGS, 1906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&NetLogSpdySettingsCallback, host_port_pair(), 1907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) clear_persisted)); 1908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnSetting(SpdySettingsIds id, 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 flags, 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 value) { 1914ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1917ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1918ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleSetting(id, value); 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_server_properties_->SetSpdySetting( 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_port_pair(), 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id, 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<SpdySettingsFlags>(flags), 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value); 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_settings_ = true; 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Log the setting. 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_RECV_SETTING, 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdySettingCallback, 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id, static_cast<SpdySettingsFlags>(flags), value)); 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SpdySession::OnSendCompressedFrame( 19357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdyStreamId stream_id, 19367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdyFrameType type, 19377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t payload_len, 19387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t frame_len) { 19397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (type != SYN_STREAM) 19407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(buffered_spdy_framer_.get()); 19437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t compressed_len = 19447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch frame_len - buffered_spdy_framer_->GetSynStreamMinimumSize(); 19457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 19467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (payload_len) { 19477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Make sure we avoid early decimal truncation. 19487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int compression_pct = 100 - (100 * compressed_len) / payload_len; 19497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage", 19507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch compression_pct); 19517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 19527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint SpdySession::OnInitialResponseHeadersReceived( 1955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SpdyHeaderBlock& response_headers, 1956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Time response_time, 1957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeTicks recv_first_byte_time, 1958eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStream* stream) { 1959ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1960a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) SpdyStreamId stream_id = stream->stream_id(); 1961a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // May invalidate |stream|. 1962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rv = stream->OnInitialResponseHeadersReceived( 1963eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch response_headers, response_time, recv_first_byte_time); 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv < 0) { 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 1966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(active_streams_.find(stream_id) == active_streams_.end()); 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return rv; 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnSynStream(SpdyStreamId stream_id, 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId associated_stream_id, 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyPriority priority, 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 credential_slot, 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fin, 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool unidirectional, 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& headers) { 1978ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 1979ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1980ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 1981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 1982ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Time response_time = base::Time::Now(); 1984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::TimeTicks recv_first_byte_time = time_func_(); 1985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log_.IsLoggingAllEvents()) { 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM, 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdySynCallback, 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &headers, fin, unidirectional, 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, associated_stream_id)); 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Server-initiated streams should have even sequence numbers. 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((stream_id & 0x1) != 0) { 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Received invalid OnSyn stream id " << stream_id; 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsStreamActive(stream_id)) { 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Received OnSyn for active stream " << stream_id; 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) RequestPriority request_priority = 2006a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ConvertSpdyPriorityToRequestPriority(priority, GetProtocolVersion()); 2007a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2008ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_GOING_AWAY) { 2009ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // TODO(akalin): This behavior isn't in the SPDY spec, although it 2010ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // probably should be. 2011bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame(stream_id, request_priority, 2012bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch RST_STREAM_REFUSED_STREAM, 2013bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch "OnSyn received when going away"); 2014ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2015ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2016ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (associated_stream_id == 0) { 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string description = base::StringPrintf( 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Received invalid OnSyn associated stream id %d for stream %d", 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) associated_stream_id, stream_id); 2021bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame(stream_id, request_priority, 2022bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch RST_STREAM_REFUSED_STREAM, description); 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_pushed_count_++; 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): DCHECK that this is a GET method? 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the response had a URL for us. 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion(), true); 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gurl.is_valid()) { 2033bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame( 2034bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR, 2035bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch "Pushed stream url was invalid: " + gurl.spec()); 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify we have a valid stream association. 2040a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::iterator associated_it = 2041a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) active_streams_.find(associated_stream_id); 2042a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (associated_it == active_streams_.end()) { 2043bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame( 2044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream_id, request_priority, RST_STREAM_INVALID_STREAM, 2045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::StringPrintf( 2046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "Received OnSyn with inactive associated stream %d", 2047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch associated_stream_id)); 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the SYN advertises the same origin as its associated stream. 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bypass this check if and only if this session is with a SPDY proxy that 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is trusted explicitly via the --trusted-spdy-proxy switch. 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trusted_spdy_proxy_.Equals(host_port_pair())) { 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disallow pushing of HTTPS content. 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gurl.SchemeIs("https")) { 2057bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame( 2058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream_id, request_priority, RST_STREAM_REFUSED_STREAM, 2059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::StringPrintf( 2060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "Rejected push of Cross Origin HTTPS content %d", 2061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch associated_stream_id)); 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2064ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch GURL associated_url(associated_it->second.stream->GetUrlFromHeaders()); 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (associated_url.GetOrigin() != gurl.GetOrigin()) { 2066bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame( 2067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream_id, request_priority, RST_STREAM_REFUSED_STREAM, 2068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::StringPrintf( 2069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "Rejected Cross Origin Push Stream %d", 2070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch associated_stream_id)); 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There should not be an existing pushed stream with the same path. 2076ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PushedStreamMap::iterator pushed_it = 2077ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unclaimed_pushed_streams_.lower_bound(gurl); 2078ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (pushed_it != unclaimed_pushed_streams_.end() && 2079ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pushed_it->first == gurl) { 2080bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch EnqueueResetStreamFrame( 2081bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch stream_id, request_priority, RST_STREAM_PROTOCOL_ERROR, 2082bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch "Received duplicate pushed stream with url: " + 2083bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch gurl.spec()); 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2087a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) scoped_ptr<SpdyStream> stream( 2088ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new SpdyStream(SPDY_PUSH_STREAM, GetWeakPtr(), gurl, 208990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) request_priority, 20902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_initial_send_window_size_, 20912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_initial_recv_window_size_, 209290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) net_log_)); 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->set_stream_id(stream_id); 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteExpiredPushedStreams(); 2096ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PushedStreamMap::iterator inserted_pushed_it = 2097ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unclaimed_pushed_streams_.insert( 2098ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pushed_it, 2099ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch std::make_pair(gurl, PushedStreamInfo(stream_id, time_func_()))); 2100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(inserted_pushed_it != pushed_it); 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) InsertActivatedStream(stream.Pass()); 2103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); 2105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (active_it == active_streams_.end()) { 2106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NOTREACHED(); 2107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 2108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse the headers. 2111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (OnInitialResponseHeadersReceived( 2112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch headers, response_time, 2113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch recv_first_byte_time, active_it->second.stream) != OK) 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StatsCounter push_requests("spdy.pushed_streams"); 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_requests.Increment(); 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::DeleteExpiredPushedStreams() { 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unclaimed_pushed_streams_.empty()) 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that adequate time has elapsed since the last sweep. 21252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (time_func_() < next_unclaimed_push_stream_sweep_time_) 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Gather old streams to delete. 21292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks minimum_freshness = time_func_() - 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); 2131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<SpdyStreamId> streams_to_close; 2132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin(); 2133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != unclaimed_pushed_streams_.end(); ++it) { 2134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (minimum_freshness > it->second.creation_time) 2135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch streams_to_close.push_back(it->second.stream_id); 2136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (std::vector<SpdyStreamId>::const_iterator to_close_it = 2139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch streams_to_close.begin(); 2140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch to_close_it != streams_to_close.end(); ++to_close_it) { 2141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ActiveStreamMap::iterator active_it = active_streams_.find(*to_close_it); 2142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (active_it == active_streams_.end()) 2143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 2144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LogAbandonedActiveStream(active_it, ERR_INVALID_SPDY_STREAM); 2146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // CloseActiveStreamIterator() will remove the stream from 2147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // |unclaimed_pushed_streams_|. 2148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseActiveStreamIterator(active_it, ERR_INVALID_SPDY_STREAM); 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 21512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_unclaimed_push_stream_sweep_time_ = time_func_() + 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnSynReply(SpdyStreamId stream_id, 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fin, 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& headers) { 2158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 2159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Time response_time = base::Time::Now(); 2164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::TimeTicks recv_first_byte_time = time_func_(); 2165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log().IsLoggingAllEvents()) { 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_SYN_REPLY, 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdySynCallback, 21702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &headers, fin, false, // not unidirectional 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, 0)); 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::iterator it = active_streams_.find(stream_id); 2175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (it == active_streams_.end()) { 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: it may just be that the stream was cancelled. 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStream* stream = it->second.stream; 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(stream->stream_id(), stream_id); 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!it->second.waiting_for_syn_reply) { 2184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& error = 2185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "Received duplicate SYN_REPLY for stream."; 2186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); 2187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResetStreamIterator(it, RST_STREAM_STREAM_IN_USE, error); 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it->second.waiting_for_syn_reply = false; 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ignore_result(OnInitialResponseHeadersReceived( 2193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch headers, response_time, recv_first_byte_time, stream)); 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnHeaders(SpdyStreamId stream_id, 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fin, 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& headers) { 2199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 2200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log().IsLoggingAllEvents()) { 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_RECV_HEADERS, 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdySynCallback, 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &headers, fin, /*unidirectional=*/false, 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, 0)); 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2212a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::iterator it = active_streams_.find(stream_id); 2213a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (it == active_streams_.end()) { 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: it may just be that the stream was cancelled. 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStream* stream = it->second.stream; 2220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(stream->stream_id(), stream_id); 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int rv = stream->OnAdditionalResponseHeadersReceived(headers); 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv < 0) { 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(rv, ERR_IO_PENDING); 2225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(active_streams_.find(stream_id) == active_streams_.end()); 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdySession::OnRstStream(SpdyStreamId stream_id, 22302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyRstStreamStatus status) { 2231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 2232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string description; 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_RST_STREAM, 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdyRstCallback, 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, status, &description)); 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2242a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::iterator it = active_streams_.find(stream_id); 2243a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (it == active_streams_.end()) { 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: it may just be that the stream was cancelled. 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Received RST for invalid stream" << stream_id; 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(it->second.stream->stream_id(), stream_id); 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == 0) { 2252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it->second.stream->OnDataReceived(scoped_ptr<SpdyBuffer>()); 22532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (status == RST_STREAM_REFUSED_STREAM) { 2254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CloseActiveStreamIterator(it, ERR_SPDY_SERVER_REFUSED_STREAM); 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordProtocolErrorHistogram( 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM); 2258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it->second.stream->LogStreamError( 22592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ERR_SPDY_PROTOCOL_ERROR, 22602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPrintf("SPDY stream closed with status: %d", status)); 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): Map from Spdy-protocol errors to something sensical. 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, it doesn't matter much - it is a protocol error. 2263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CloseActiveStreamIterator(it, ERR_SPDY_PROTOCOL_ERROR); 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyGoAwayStatus status) { 2269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 2270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SPDY_SESSION_GOAWAY, 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdyGoAwayCallback, 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_accepted_stream_id, 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_streams_.size(), 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unclaimed_pushed_streams_.size(), 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status)); 2280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ < STATE_GOING_AWAY) { 2281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch availability_state_ = STATE_GOING_AWAY; 2282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // |pool_| will be NULL when |InitializeWithSocket()| is in the 2283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // call stack. 2284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (pool_) 2285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pool_->MakeSessionUnavailable(GetWeakPtr()); 2286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch StartGoingAway(last_accepted_stream_id, ERR_ABORTED); 2288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // This is to handle the case when we already don't have any active 2289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // streams (i.e., StartGoingAway() did nothing). Otherwise, we have 2290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // active streams and so the last one being closed will finish the 2291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // going away process (see DeleteStream()). 2292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MaybeFinishGoingAway(); 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnPing(uint32 unique_id) { 2296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 2297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_PING, 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdyPingCallback, unique_id, "received")); 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send response to a PING from server. 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unique_id % 2 == 0) { 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WritePingFrame(unique_id); 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --pings_in_flight_; 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pings_in_flight_ < 0) { 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordProtocolErrorHistogram(PROTOCOL_ERROR_UNEXPECTED_PING); 2314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = 2315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(ERR_SPDY_PROTOCOL_ERROR, "pings_in_flight_ is < 0."); 2316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pings_in_flight_ = 0; 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pings_in_flight_ > 0) 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will record RTT in histogram when there are no more client sent 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pings_in_flight_. 2326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch RecordPingRTTHistogram(time_func_() - last_ping_sent_time_); 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::OnWindowUpdate(SpdyStreamId stream_id, 23302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 delta_window_size) { 2331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 2332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 23362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LE(delta_window_size, static_cast<uint32>(kint32max)); 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 23382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_RECEIVED_WINDOW_UPDATE_FRAME, 23392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&NetLogSpdyWindowUpdateFrameCallback, 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, delta_window_size)); 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2342a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (stream_id == kSessionFlowControlStreamId) { 2343a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // WINDOW_UPDATE for the session. 2344a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (flow_control_state_ < FLOW_CONTROL_STREAM_AND_SESSION) { 2345a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LOG(WARNING) << "Received WINDOW_UPDATE for session when " 2346a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) << "session flow control is not turned on"; 2347a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // TODO(akalin): Record an error and close the session. 2348a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 2349a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 23502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2351a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (delta_window_size < 1u) { 2352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); 2353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = DoCloseSession( 2354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ERR_SPDY_PROTOCOL_ERROR, 2355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "Received WINDOW_UPDATE with an invalid delta_window_size " + 2356a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::UintToString(delta_window_size)); 2357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); 2358a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 2359a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 2360a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2361a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) IncreaseSendWindowSize(static_cast<int32>(delta_window_size)); 2362a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 2363a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // WINDOW_UPDATE for a stream. 2364a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (flow_control_state_ < FLOW_CONTROL_STREAM) { 2365a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // TODO(akalin): Record an error and close the session. 2366a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LOG(WARNING) << "Received WINDOW_UPDATE for stream " << stream_id 2367a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) << " when flow control is not turned on"; 2368a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 2369a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 2370a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ActiveStreamMap::iterator it = active_streams_.find(stream_id); 2372a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2373a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (it == active_streams_.end()) { 2374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // NOTE: it may just be that the stream was cancelled. 2375a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id; 2376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 2377a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 2378a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyStream* stream = it->second.stream; 2380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(stream->stream_id(), stream_id); 2381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2382a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (delta_window_size < 1u) { 2383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResetStreamIterator(it, 2384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RST_STREAM_FLOW_CONTROL_ERROR, 2385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::StringPrintf( 2386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "Received WINDOW_UPDATE with an invalid " 2387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "delta_window_size %ud", delta_window_size)); 2388a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 23892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(it->second.stream->stream_id(), stream_id); 2392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it->second.stream->IncreaseSendWindowSize( 2393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static_cast<int32>(delta_window_size)); 23942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid SpdySession::OnPushPromise(SpdyStreamId stream_id, 23987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdyStreamId promised_stream_id) { 23997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(akalin): Handle PUSH_PROMISE frames. 24007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 24017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 24022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, 24032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 delta_window_size) { 24042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 2405a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 2406a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CHECK(it != active_streams_.end()); 2407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(it->second.stream->stream_id(), stream_id); 2408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SendWindowUpdateFrame( 2409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream_id, delta_window_size, it->second.stream->priority()); 24102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SpdySession::SendInitialData() { 2413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(enable_sending_initial_data_); 2414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 2415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (send_connection_header_prefix_) { 2417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK_EQ(protocol_, kProtoHTTP2Draft04); 2418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) scoped_ptr<SpdyFrame> connection_header_prefix_frame( 2419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) new SpdyFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), 2420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kHttp2ConnectionHeaderPrefixSize, 2421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) false /* take_ownership */)); 2422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Count the prefix as part of the subsequent SETTINGS frame. 2423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EnqueueSessionWrite(HIGHEST, SETTINGS, 2424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) connection_header_prefix_frame.Pass()); 2425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 2426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // First, notify the server about the settings they should use when 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // communicating with us. 2429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SettingsMap settings_map; 2430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Create a new settings frame notifying the server of our 2431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // max concurrent streams and initial window size. 2432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = 2433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); 2434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (flow_control_state_ >= FLOW_CONTROL_STREAM && 2435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { 2436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = 2437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 2438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stream_initial_recv_window_size_); 2439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 2440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SendSettings(settings_map); 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Next, notify the server about our initial recv window size. 2443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { 2444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Bump up the receive window size to the real initial value. This 2445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // has to go here since the WINDOW_UPDATE frame sent by 2446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. 2447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_GT(kDefaultInitialRecvWindowSize, session_recv_window_size_); 2448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // This condition implies that |kDefaultInitialRecvWindowSize| - 2449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // |session_recv_window_size_| doesn't overflow. 2450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK_GT(session_recv_window_size_, 0); 2451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch IncreaseRecvWindowSize( 2452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kDefaultInitialRecvWindowSize - session_recv_window_size_); 2453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Finally, notify the server about the settings they have 2456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // previously told us to use when communicating with them (after 2457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // applying them). 2458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const SettingsMap& server_settings_map = 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_server_properties_->GetSpdySettings(host_port_pair()); 2460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (server_settings_map.empty()) 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SettingsMap::const_iterator it = 2464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) server_settings_map.find(SETTINGS_CURRENT_CWND); 2465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) uint32 cwnd = (it != server_settings_map.end()) ? it->second.second : 0; 2466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100); 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (SettingsMap::const_iterator it = server_settings_map.begin(); 2469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it != server_settings_map.end(); ++it) { 2470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const SpdySettingsIds new_id = it->first; 2471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const uint32 new_val = it->second.second; 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleSetting(new_id, new_val); 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SendSettings(server_settings_map); 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::SendSettings(const SettingsMap& settings) { 2480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 2481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, 2484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&NetLogSpdySendSettingsCallback, &settings)); 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the SETTINGS frame and send it. 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 24882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> settings_frame( 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_spdy_framer_->CreateSettings(settings)); 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sent_settings_ = true; 2491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnqueueSessionWrite(HIGHEST, SETTINGS, settings_frame.Pass()); 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::HandleSetting(uint32 id, uint32 value) { 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (id) { 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_MAX_CONCURRENT_STREAMS: 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_concurrent_streams_ = std::min(static_cast<size_t>(value), 24982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kMaxConcurrentStreamLimit); 24992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProcessPendingStreamRequests(); 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 25012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SETTINGS_INITIAL_WINDOW_SIZE: { 25022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (flow_control_state_ < FLOW_CONTROL_STREAM) { 2503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log().AddEvent( 2504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_INITIAL_WINDOW_SIZE_NO_FLOW_CONTROL); 25052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (value > static_cast<uint32>(kint32max)) { 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 2510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_INITIAL_WINDOW_SIZE_OUT_OF_RANGE, 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("initial_window_size", value)); 25122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SETTINGS_INITIAL_WINDOW_SIZE updates initial_send_window_size_ only. 2516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int32 delta_window_size = 2517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<int32>(value) - stream_initial_send_window_size_; 2518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream_initial_send_window_size_ = static_cast<int32>(value); 25192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateStreamsSendWindowSize(delta_window_size); 25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log().AddEvent( 25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE, 25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::IntegerCallback("delta_window_size", delta_window_size)); 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 25242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { 25292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 2530a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for (ActiveStreamMap::iterator it = active_streams_.begin(); 2531a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) it != active_streams_.end(); ++it) { 2532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it->second.stream->AdjustSendWindowSize(delta_window_size); 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for (CreatedStreamSet::const_iterator it = created_streams_.begin(); 2536a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) it != created_streams_.end(); it++) { 2537a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) (*it)->AdjustSendWindowSize(delta_window_size); 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::SendPrefacePingIfNoneInFlight() { 25422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pings_in_flight_ || !enable_ping_based_connection_checking_) 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::TimeTicks now = time_func_(); 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no activity in the session, then send a preface-PING. 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendPrefacePing(); 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::SendPrefacePing() { 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WritePingFrame(next_ping_id_); 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdySession::SendWindowUpdateFrame(SpdyStreamId stream_id, 25562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 delta_window_size, 25572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RequestPriority priority) { 25582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_GE(flow_control_state_, FLOW_CONTROL_STREAM); 2559a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 2560a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (it != active_streams_.end()) { 2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK_EQ(it->second.stream->stream_id(), stream_id); 25622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 25632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 25642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_EQ(stream_id, kSessionFlowControlStreamId); 25652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.AddEvent( 25682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE_FRAME, 25692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&NetLogSpdyWindowUpdateFrameCallback, 25702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_id, delta_window_size)); 25712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 25732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> window_update_frame( 25742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); 2575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnqueueSessionWrite(priority, WINDOW_UPDATE, window_update_frame.Pass()); 25762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::WritePingFrame(uint32 unique_id) { 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buffered_spdy_framer_.get()); 25802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> ping_frame( 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_spdy_framer_->CreatePingFrame(unique_id)); 2582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EnqueueSessionWrite(HIGHEST, PING, ping_frame.Pass()); 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_log().IsLoggingAllEvents()) { 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log().AddEvent( 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SPDY_SESSION_PING, 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogSpdyPingCallback, unique_id, "sent")); 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unique_id % 2 != 0) { 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_ping_id_ += 2; 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++pings_in_flight_; 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PlanToCheckPingStatus(); 2593ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch last_ping_sent_time_ = time_func_(); 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::PlanToCheckPingStatus() { 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (check_ping_status_pending_) 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check_ping_status_pending_ = true; 260290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), 2605ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch time_func_()), hung_interval_); 26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) { 2609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(!in_io_loop_); 2610ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 2611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we got a response back for all PINGs we had sent. 26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pings_in_flight_ == 0) { 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check_ping_status_pending_ = false; 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(check_ping_status_pending_); 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2620ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::TimeTicks now = time_func_(); 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta delay = hung_interval_ - (now - last_activity_time_); 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delay.InMilliseconds() < 0 || last_activity_time_ < last_check_time) { 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Track all failed PING messages in a separate bucket. 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta kFailedPing = 26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromInternalValue(INT_MAX); 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordPingRTTHistogram(kFailedPing); 2628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = 2629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DoCloseSession(ERR_SPDY_PING_FAILED, "Failed ping."); 2630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, SESSION_CLOSED_AND_REMOVED); 26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the status of connection after a delay. 263590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(), 26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) now), 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delay); 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) { 26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration); 26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::RecordProtocolErrorHistogram( 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyProtocolErrorDetails details) { 2648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails2", details, 26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NUM_SPDY_PROTOCOL_ERROR_DETAILS); 26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EndsWith(host_port_pair().host(), "google.com", false)) { 2651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails_Google2", details, 26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NUM_SPDY_PROTOCOL_ERROR_DETAILS); 26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySession::RecordHistograms() { 26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession", 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_initiated_count_, 26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 300, 50); 26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession", 26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_pushed_count_, 26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 300, 50); 26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession", 26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_pushed_and_claimed_count_, 26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 300, 50); 26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsAbandonedPerSession", 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams_abandoned_count_, 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 300, 50); 26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.SpdySettingsSent", 26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sent_settings_ ? 1 : 0, 2); 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.SpdySettingsReceived", 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_settings_ ? 1 : 0, 2); 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamStallsPerSession", 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stalled_streams_, 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 300, 50); 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionsWithStalls", 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stalled_streams_ > 0 ? 1 : 0, 2); 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (received_settings_) { 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enumerate the saved settings, and set histograms for it. 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SettingsMap& settings_map = 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_server_properties_->GetSpdySettings(host_port_pair()); 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsMap::const_iterator it; 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = settings_map.begin(); it != settings_map.end(); ++it) { 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdySettingsIds id = it->first; 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 val = it->second.second; 26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (id) { 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_CURRENT_CWND: 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record several different histograms to see if cwnd converges 26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for larger volumes of data being sent. 26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd", 26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val, 1, 200, 100); 26942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_bytes_received_ > 10 * 1024) { 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd10K", 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val, 1, 200, 100); 26972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_bytes_received_ > 25 * 1024) { 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd25K", 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val, 1, 200, 100); 27002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_bytes_received_ > 50 * 1024) { 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd50K", 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val, 1, 200, 100); 27032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_bytes_received_ > 100 * 1024) { 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd100K", 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val, 1, 200, 100); 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_ROUND_TRIP_TIME: 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRTT", 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val, 1, 1200, 100); 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_DOWNLOAD_RETRANS_RATE: 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRetransRate", 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val, 1, 100, 50); 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void SpdySession::CompleteStreamRequest( 27273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::WeakPtr<SpdyStreamRequest>& pending_request) { 27282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Abort if the request has already been cancelled. 27293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!pending_request) 27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2732a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream; 27332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = CreateStream(*pending_request, &stream); 27342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2735a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (rv == OK) { 27363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(stream); 27373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pending_request->OnRequestCompleteSuccess(stream); 2738a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 27393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!stream); 2740a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pending_request->OnRequestCompleteFailure(rv); 2741a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocket* SpdySession::GetSSLClientSocket() const { 27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_secure_) 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocket* ssl_socket = 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<SSLClientSocket*>(connection_->socket()); 27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ssl_socket); 27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ssl_socket; 27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::OnWriteBufferConsumed( 2754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t frame_payload_size, 2755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t consume_size, 2756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyBuffer::ConsumeSource consume_source) { 2757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We can be called with |in_io_loop_| set if a write SpdyBuffer is 2758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // deleted (e.g., a stream is closed due to incoming data). 2759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 27632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (consume_source == SpdyBuffer::DISCARD) { 2766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If we're discarding a frame or part of it, increase the send 2767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // window by the number of discarded bytes. (Although if we're 2768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // discarding part of a frame, it's probably because of a write 2769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // error and we'll be tearing down the session soon.) 2770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t remaining_payload_bytes = std::min(consume_size, frame_payload_size); 2771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(remaining_payload_bytes, 0u); 2772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IncreaseSendWindowSize(static_cast<int32>(remaining_payload_bytes)); 2773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // For consumed bytes, the send window is increased when we receive 2775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // a WINDOW_UPDATE frame. 2776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 27772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::IncreaseSendWindowSize(int32 delta_window_size) { 2779ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We can be called with |in_io_loop_| set if a SpdyBuffer is 2780ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // deleted (e.g., a stream is closed due to incoming data). 2781ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2782ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 2783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 27842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GE(delta_window_size, 1); 27852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Check for overflow. 27872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 max_delta_window_size = kint32max - session_send_window_size_; 27882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delta_window_size > max_delta_window_size) { 2789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); 2790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = DoCloseSession( 2791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ERR_SPDY_PROTOCOL_ERROR, 2792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "Received WINDOW_UPDATE [delta: " + 2793ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::IntToString(delta_window_size) + 2794ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch "] for session overflows session_send_window_size_ [current: " + 2795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::IntToString(session_send_window_size_) + "]"); 2796ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(result, SESSION_ALREADY_CLOSED); 27972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 27982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 27992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_send_window_size_ += delta_window_size; 28012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.AddEvent( 28032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, 28042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&NetLogSpdySessionWindowUpdateCallback, 28052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delta_window_size, session_send_window_size_)); 28062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!IsSendStalled()); 28082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResumeSendStalledStreams(); 28092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 28102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::DecreaseSendWindowSize(int32 delta_window_size) { 2812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 2813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We only call this method when sending a frame. Therefore, 2816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |delta_window_size| should be within the valid frame size range. 2817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(delta_window_size, 1); 2818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize); 2819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |send_window_size_| should have been at least |delta_window_size| for 2821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // this call to happen. 2822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(session_send_window_size_, delta_window_size); 2823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_send_window_size_ -= delta_window_size; 2825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log_.AddEvent( 2827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_UPDATE_SEND_WINDOW, 2828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) -delta_window_size, session_send_window_size_)); 2830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 2831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::OnReadBufferConsumed( 2833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t consume_size, 2834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SpdyBuffer::ConsumeSource consume_source) { 2835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We can be called with |in_io_loop_| set if a read SpdyBuffer is 2836ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // deleted (e.g., discarded by a SpdyReadQueue). 2837ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2838ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (availability_state_ == STATE_CLOSED) 2839ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 2840ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2842c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(consume_size, 1u); 2843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(consume_size, static_cast<size_t>(kint32max)); 2844ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IncreaseRecvWindowSize(static_cast<int32>(consume_size)); 2846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 2847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::IncreaseRecvWindowSize(int32 delta_window_size) { 2849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_NE(availability_state_, STATE_CLOSED); 2850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(session_unacked_recv_window_bytes_, 0); 2852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_); 2853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(delta_window_size, 1); 2854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check for overflow. 2855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(delta_window_size, kint32max - session_recv_window_size_); 2856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_recv_window_size_ += delta_window_size; 2858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log_.AddEvent( 2859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, 2860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delta_window_size, session_recv_window_size_)); 2862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_unacked_recv_window_bytes_ += delta_window_size; 2864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (session_unacked_recv_window_bytes_ > kSpdySessionInitialWindowSize / 2) { 2865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SendWindowUpdateFrame(kSessionFlowControlStreamId, 2866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_unacked_recv_window_bytes_, 2867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HIGHEST); 2868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_unacked_recv_window_bytes_ = 0; 2869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 2871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) { 2873ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHECK(in_io_loop_); 2874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 2875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(delta_window_size, 1); 2876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Since we never decrease the initial receive window size, 2878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |delta_window_size| should never cause |recv_window_size_| to go 2879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // negative. If we do, the receive window isn't being respected. 2880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (delta_window_size > session_recv_window_size_) { 2881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RecordProtocolErrorHistogram(PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION); 2882ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseSessionResult result = DoCloseSession( 2883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ERR_SPDY_PROTOCOL_ERROR, 2884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "delta_window_size is " + base::IntToString(delta_window_size) + 2885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " in DecreaseRecvWindowSize, which is larger than the receive " + 2886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "window size of " + base::IntToString(session_recv_window_size_)); 2887ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(result, SESSION_CLOSED_BUT_NOT_REMOVED); 2888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 2889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) session_recv_window_size_ -= delta_window_size; 2892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net_log_.AddEvent( 2893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, 2894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&NetLogSpdySessionWindowUpdateCallback, 2895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) -delta_window_size, session_recv_window_size_)); 2896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 2897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2898a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void SpdySession::QueueSendStalledStream(const SpdyStream& stream) { 2899a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(stream.send_stalled_by_flow_control()); 2900a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream_send_unstall_queue_[stream.priority()].push_back(stream.stream_id()); 29012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 29022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdySession::ResumeSendStalledStreams() { 29042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(flow_control_state_, FLOW_CONTROL_STREAM_AND_SESSION); 29052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We don't have to worry about new streams being queued, since 29072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doing so would cause IsSendStalled() to return true. But we do 29082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have to worry about streams being closed, as well as ourselves 29092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // being closed. 29102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2911ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while (availability_state_ != STATE_CLOSED && !IsSendStalled()) { 29122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t old_size = 0; 29132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (DCHECK_IS_ON()) 29142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_size = GetTotalSize(stream_send_unstall_queue_); 29152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id = PopStreamToPossiblyResume(); 29172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (stream_id == 0) 29182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 29192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); 29202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The stream may actually still be send-stalled after this (due 29212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to its own send window) but that's okay -- it'll then be 29222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // resumed once its send window increases. 29232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it != active_streams_.end()) 2924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it->second.stream->PossiblyResumeIfSendStalled(); 29252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The size should decrease unless we got send-stalled again. 29272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsSendStalled()) 29282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LT(GetTotalSize(stream_send_unstall_queue_), old_size); 29292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 29302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 29312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyStreamId SpdySession::PopStreamToPossiblyResume() { 29332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = NUM_PRIORITIES - 1; i >= 0; --i) { 29342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::deque<SpdyStreamId>* queue = &stream_send_unstall_queue_[i]; 29352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!queue->empty()) { 29362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id = queue->front(); 29372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queue->pop_front(); 29382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return stream_id; 29392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 29402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 29412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 29422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 29432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 2945