spdy_session.cc 137 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/spdy/spdy_session.h"
  5. #include <algorithm>
  6. #include <limits>
  7. #include <map>
  8. #include <string>
  9. #include <tuple>
  10. #include <utility>
  11. #include "base/bind.h"
  12. #include "base/containers/contains.h"
  13. #include "base/location.h"
  14. #include "base/logging.h"
  15. #include "base/memory/raw_ptr.h"
  16. #include "base/metrics/histogram_functions.h"
  17. #include "base/metrics/histogram_macros.h"
  18. #include "base/rand_util.h"
  19. #include "base/strings/abseil_string_conversions.h"
  20. #include "base/strings/strcat.h"
  21. #include "base/strings/string_number_conversions.h"
  22. #include "base/strings/string_split.h"
  23. #include "base/strings/string_util.h"
  24. #include "base/strings/stringprintf.h"
  25. #include "base/strings/utf_string_conversions.h"
  26. #include "base/task/single_thread_task_runner.h"
  27. #include "base/threading/thread_task_runner_handle.h"
  28. #include "base/time/time.h"
  29. #include "base/trace_event/memory_usage_estimator.h"
  30. #include "base/trace_event/trace_event.h"
  31. #include "base/values.h"
  32. #include "net/base/features.h"
  33. #include "net/base/proxy_server.h"
  34. #include "net/base/proxy_string_util.h"
  35. #include "net/base/url_util.h"
  36. #include "net/cert/asn1_util.h"
  37. #include "net/cert/cert_verify_result.h"
  38. #include "net/cert/ct_policy_status.h"
  39. #include "net/http/http_network_session.h"
  40. #include "net/http/http_server_properties.h"
  41. #include "net/http/http_util.h"
  42. #include "net/http/http_vary_data.h"
  43. #include "net/http/transport_security_state.h"
  44. #include "net/log/net_log.h"
  45. #include "net/log/net_log_capture_mode.h"
  46. #include "net/log/net_log_event_type.h"
  47. #include "net/log/net_log_source_type.h"
  48. #include "net/log/net_log_with_source.h"
  49. #include "net/nqe/network_quality_estimator.h"
  50. #include "net/quic/quic_http_utils.h"
  51. #include "net/socket/client_socket_handle.h"
  52. #include "net/socket/socket.h"
  53. #include "net/socket/ssl_client_socket.h"
  54. #include "net/spdy/alps_decoder.h"
  55. #include "net/spdy/header_coalescer.h"
  56. #include "net/spdy/spdy_buffer_producer.h"
  57. #include "net/spdy/spdy_http_utils.h"
  58. #include "net/spdy/spdy_log_util.h"
  59. #include "net/spdy/spdy_session_pool.h"
  60. #include "net/spdy/spdy_stream.h"
  61. #include "net/ssl/ssl_cipher_suite_names.h"
  62. #include "net/ssl/ssl_connection_status_flags.h"
  63. #include "net/third_party/quiche/src/quiche/quic/core/http/spdy_server_push_utils.h"
  64. #include "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h"
  65. #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
  66. #include "url/scheme_host_port.h"
  67. #include "url/url_constants.h"
  68. namespace net {
  69. namespace {
  70. constexpr net::NetworkTrafficAnnotationTag
  71. kSpdySessionCommandsTrafficAnnotation =
  72. net::DefineNetworkTrafficAnnotation("spdy_session_control", R"(
  73. semantics {
  74. sender: "Spdy Session"
  75. description:
  76. "Sends commands to control an HTTP/2 session."
  77. trigger:
  78. "Required control commands like initiating stream, requesting "
  79. "stream reset, changing priorities, etc."
  80. data: "No user data."
  81. destination: OTHER
  82. destination_other:
  83. "Any destination the HTTP/2 session is connected to."
  84. }
  85. policy {
  86. cookies_allowed: NO
  87. setting: "This feature cannot be disabled in settings."
  88. policy_exception_justification: "Essential for network access."
  89. }
  90. )");
  91. const int kReadBufferSize = 8 * 1024;
  92. const int kDefaultConnectionAtRiskOfLossSeconds = 10;
  93. const int kHungIntervalSeconds = 10;
  94. // Lifetime of unclaimed pushed stream, in seconds: after this period, a pushed
  95. // stream is cancelled if still not claimed.
  96. const int kPushedStreamLifetimeSeconds = 300;
  97. // Default initial value for HTTP/2 SETTINGS.
  98. const uint32_t kDefaultInitialHeaderTableSize = 4096;
  99. const uint32_t kDefaultInitialEnablePush = 1;
  100. const uint32_t kDefaultInitialInitialWindowSize = 65535;
  101. const uint32_t kDefaultInitialMaxFrameSize = 16384;
  102. // Values of Vary response header on pushed streams. This is logged to
  103. // Net.PushedStreamVaryResponseHeader, entries must not be changed.
  104. enum PushedStreamVaryResponseHeaderValues {
  105. // There is no Vary header.
  106. kNoVaryHeader = 0,
  107. // The value of Vary is empty.
  108. kVaryIsEmpty = 1,
  109. // The value of Vary is "*".
  110. kVaryIsStar = 2,
  111. // The value of Vary is "accept-encoding" (case insensitive).
  112. kVaryIsAcceptEncoding = 3,
  113. // The value of Vary contains "accept-encoding" (case insensitive) and some
  114. // other field names as well.
  115. kVaryHasAcceptEncoding = 4,
  116. // The value of Vary does not contain "accept-encoding", is not empty, and is
  117. // not "*".
  118. kVaryHasNoAcceptEncoding = 5,
  119. // The number of entries above.
  120. kNumberOfVaryEntries = 6
  121. };
  122. // These values are persisted to logs. Entries should not be renumbered, and
  123. // numeric values should never be reused.
  124. enum class SpdyAcceptChEntries {
  125. kNoEntries = 0,
  126. kOnlyValidEntries = 1,
  127. kOnlyInvalidEntries = 2,
  128. kBothValidAndInvalidEntries = 3,
  129. kMaxValue = kBothValidAndInvalidEntries,
  130. };
  131. // String literals for parsing the Vary header in a pushed response.
  132. const char kVary[] = "vary";
  133. const char kStar[] = "*";
  134. const char kAcceptEncoding[] = "accept-encoding";
  135. enum PushedStreamVaryResponseHeaderValues ParseVaryInPushedResponse(
  136. const spdy::Http2HeaderBlock& headers) {
  137. spdy::Http2HeaderBlock::iterator it = headers.find(kVary);
  138. if (it == headers.end())
  139. return kNoVaryHeader;
  140. base::StringPiece value = base::StringViewToStringPiece(it->second);
  141. if (value.empty())
  142. return kVaryIsEmpty;
  143. if (value == kStar)
  144. return kVaryIsStar;
  145. std::string lowercase_value = base::ToLowerASCII(value);
  146. if (lowercase_value == kAcceptEncoding)
  147. return kVaryIsAcceptEncoding;
  148. // Both comma and newline delimiters occur in the wild.
  149. for (const auto& substr :
  150. SplitString(lowercase_value, ",\n", base::TRIM_WHITESPACE,
  151. base::SPLIT_WANT_NONEMPTY)) {
  152. if (substr == kAcceptEncoding)
  153. return kVaryHasAcceptEncoding;
  154. }
  155. return kVaryHasNoAcceptEncoding;
  156. }
  157. // A SpdyBufferProducer implementation that creates an HTTP/2 frame by adding
  158. // stream ID to greased frame parameters.
  159. class GreasedBufferProducer : public SpdyBufferProducer {
  160. public:
  161. GreasedBufferProducer() = delete;
  162. GreasedBufferProducer(
  163. base::WeakPtr<SpdyStream> stream,
  164. const SpdySessionPool::GreasedHttp2Frame* greased_http2_frame,
  165. BufferedSpdyFramer* buffered_spdy_framer)
  166. : stream_(stream),
  167. greased_http2_frame_(greased_http2_frame),
  168. buffered_spdy_framer_(buffered_spdy_framer) {}
  169. ~GreasedBufferProducer() override = default;
  170. std::unique_ptr<SpdyBuffer> ProduceBuffer() override {
  171. const spdy::SpdyStreamId stream_id = stream_ ? stream_->stream_id() : 0;
  172. spdy::SpdyUnknownIR frame(stream_id, greased_http2_frame_->type,
  173. greased_http2_frame_->flags,
  174. greased_http2_frame_->payload);
  175. auto serialized_frame = std::make_unique<spdy::SpdySerializedFrame>(
  176. buffered_spdy_framer_->SerializeFrame(frame));
  177. return std::make_unique<SpdyBuffer>(std::move(serialized_frame));
  178. }
  179. private:
  180. base::WeakPtr<SpdyStream> stream_;
  181. const raw_ptr<const SpdySessionPool::GreasedHttp2Frame> greased_http2_frame_;
  182. raw_ptr<BufferedSpdyFramer> buffered_spdy_framer_;
  183. };
  184. bool IsSpdySettingAtDefaultInitialValue(spdy::SpdySettingsId setting_id,
  185. uint32_t value) {
  186. switch (setting_id) {
  187. case spdy::SETTINGS_HEADER_TABLE_SIZE:
  188. return value == kDefaultInitialHeaderTableSize;
  189. case spdy::SETTINGS_ENABLE_PUSH:
  190. return value == kDefaultInitialEnablePush;
  191. case spdy::SETTINGS_MAX_CONCURRENT_STREAMS:
  192. // There is no initial limit on the number of concurrent streams.
  193. return false;
  194. case spdy::SETTINGS_INITIAL_WINDOW_SIZE:
  195. return value == kDefaultInitialInitialWindowSize;
  196. case spdy::SETTINGS_MAX_FRAME_SIZE:
  197. return value == kDefaultInitialMaxFrameSize;
  198. case spdy::SETTINGS_MAX_HEADER_LIST_SIZE:
  199. // There is no initial limit on the size of the header list.
  200. return false;
  201. case spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL:
  202. return value == 0;
  203. default:
  204. // Undefined parameters have no initial value.
  205. return false;
  206. }
  207. }
  208. bool IsPushEnabled(const spdy::SettingsMap& initial_settings) {
  209. const auto it = initial_settings.find(spdy::SETTINGS_ENABLE_PUSH);
  210. // Push is enabled by default.
  211. if (it == initial_settings.end())
  212. return true;
  213. return it->second == 1;
  214. }
  215. void LogSpdyAcceptChForOriginHistogram(bool value) {
  216. base::UmaHistogramBoolean("Net.SpdySession.AcceptChForOrigin", value);
  217. }
  218. base::Value NetLogSpdyHeadersSentParams(const spdy::Http2HeaderBlock* headers,
  219. bool fin,
  220. spdy::SpdyStreamId stream_id,
  221. bool has_priority,
  222. int weight,
  223. spdy::SpdyStreamId parent_stream_id,
  224. bool exclusive,
  225. NetLogSource source_dependency,
  226. NetLogCaptureMode capture_mode) {
  227. base::Value::Dict dict;
  228. dict.Set("headers", ElideHttp2HeaderBlockForNetLog(*headers, capture_mode));
  229. dict.Set("fin", fin);
  230. dict.Set("stream_id", static_cast<int>(stream_id));
  231. dict.Set("has_priority", has_priority);
  232. if (has_priority) {
  233. dict.Set("parent_stream_id", static_cast<int>(parent_stream_id));
  234. dict.Set("weight", weight);
  235. dict.Set("exclusive", exclusive);
  236. }
  237. if (source_dependency.IsValid()) {
  238. source_dependency.AddToEventParameters(dict);
  239. }
  240. return base::Value(std::move(dict));
  241. }
  242. base::Value NetLogSpdyHeadersReceivedParams(
  243. const spdy::Http2HeaderBlock* headers,
  244. bool fin,
  245. spdy::SpdyStreamId stream_id,
  246. NetLogCaptureMode capture_mode) {
  247. base::Value::Dict dict;
  248. dict.Set("headers", ElideHttp2HeaderBlockForNetLog(*headers, capture_mode));
  249. dict.Set("fin", fin);
  250. dict.Set("stream_id", static_cast<int>(stream_id));
  251. return base::Value(std::move(dict));
  252. }
  253. base::Value NetLogSpdySessionCloseParams(int net_error,
  254. const std::string& description) {
  255. base::Value::Dict dict;
  256. dict.Set("net_error", net_error);
  257. dict.Set("description", description);
  258. return base::Value(std::move(dict));
  259. }
  260. base::Value NetLogSpdySessionParams(const HostPortProxyPair& host_pair) {
  261. base::Value::Dict dict;
  262. dict.Set("host", host_pair.first.ToString());
  263. dict.Set("proxy", ProxyServerToPacResultElement(host_pair.second));
  264. return base::Value(std::move(dict));
  265. }
  266. base::Value NetLogSpdyInitializedParams(NetLogSource source) {
  267. base::Value::Dict dict;
  268. if (source.IsValid()) {
  269. source.AddToEventParameters(dict);
  270. }
  271. dict.Set("protocol", NextProtoToString(kProtoHTTP2));
  272. return base::Value(std::move(dict));
  273. }
  274. base::Value NetLogSpdySendSettingsParams(const spdy::SettingsMap* settings) {
  275. base::Value::Dict dict;
  276. base::Value::List settings_list;
  277. for (const auto& setting : *settings) {
  278. const spdy::SpdySettingsId id = setting.first;
  279. const uint32_t value = setting.second;
  280. settings_list.Append(
  281. base::StringPrintf("[id:%u (%s) value:%u]", id,
  282. spdy::SettingsIdToString(id).c_str(), value));
  283. }
  284. dict.Set("settings", std::move(settings_list));
  285. return base::Value(std::move(dict));
  286. }
  287. base::Value NetLogSpdyRecvAcceptChParams(spdy::AcceptChOriginValuePair entry) {
  288. base::Value::Dict dict;
  289. dict.Set("origin", entry.origin);
  290. dict.Set("accept_ch", entry.value);
  291. return base::Value(std::move(dict));
  292. }
  293. base::Value NetLogSpdyRecvSettingParams(spdy::SpdySettingsId id,
  294. uint32_t value) {
  295. base::Value::Dict dict;
  296. dict.Set("id", base::StringPrintf("%u (%s)", id,
  297. spdy::SettingsIdToString(id).c_str()));
  298. dict.Set("value", static_cast<int>(value));
  299. return base::Value(std::move(dict));
  300. }
  301. base::Value NetLogSpdyWindowUpdateFrameParams(spdy::SpdyStreamId stream_id,
  302. uint32_t delta) {
  303. base::Value::Dict dict;
  304. dict.Set("stream_id", static_cast<int>(stream_id));
  305. dict.Set("delta", static_cast<int>(delta));
  306. return base::Value(std::move(dict));
  307. }
  308. base::Value NetLogSpdySessionWindowUpdateParams(int32_t delta,
  309. int32_t window_size) {
  310. base::Value::Dict dict;
  311. dict.Set("delta", delta);
  312. dict.Set("window_size", window_size);
  313. return base::Value(std::move(dict));
  314. }
  315. base::Value NetLogSpdyDataParams(spdy::SpdyStreamId stream_id,
  316. int size,
  317. bool fin) {
  318. base::Value::Dict dict;
  319. dict.Set("stream_id", static_cast<int>(stream_id));
  320. dict.Set("size", size);
  321. dict.Set("fin", fin);
  322. return base::Value(std::move(dict));
  323. }
  324. base::Value NetLogSpdyRecvRstStreamParams(spdy::SpdyStreamId stream_id,
  325. spdy::SpdyErrorCode error_code) {
  326. base::Value::Dict dict;
  327. dict.Set("stream_id", static_cast<int>(stream_id));
  328. dict.Set("error_code", base::StringPrintf("%u (%s)", error_code,
  329. ErrorCodeToString(error_code)));
  330. return base::Value(std::move(dict));
  331. }
  332. base::Value NetLogSpdySendRstStreamParams(spdy::SpdyStreamId stream_id,
  333. spdy::SpdyErrorCode error_code,
  334. const std::string& description) {
  335. base::Value::Dict dict;
  336. dict.Set("stream_id", static_cast<int>(stream_id));
  337. dict.Set("error_code", base::StringPrintf("%u (%s)", error_code,
  338. ErrorCodeToString(error_code)));
  339. dict.Set("description", description);
  340. return base::Value(std::move(dict));
  341. }
  342. base::Value NetLogSpdyPingParams(spdy::SpdyPingId unique_id,
  343. bool is_ack,
  344. const char* type) {
  345. base::Value::Dict dict;
  346. dict.Set("unique_id", static_cast<int>(unique_id));
  347. dict.Set("type", type);
  348. dict.Set("is_ack", is_ack);
  349. return base::Value(std::move(dict));
  350. }
  351. base::Value NetLogSpdyRecvGoAwayParams(spdy::SpdyStreamId last_stream_id,
  352. int active_streams,
  353. int unclaimed_streams,
  354. spdy::SpdyErrorCode error_code,
  355. base::StringPiece debug_data,
  356. NetLogCaptureMode capture_mode) {
  357. base::Value::Dict dict;
  358. dict.Set("last_accepted_stream_id", static_cast<int>(last_stream_id));
  359. dict.Set("active_streams", active_streams);
  360. dict.Set("unclaimed_streams", unclaimed_streams);
  361. dict.Set("error_code", base::StringPrintf("%u (%s)", error_code,
  362. ErrorCodeToString(error_code)));
  363. dict.Set("debug_data",
  364. ElideGoAwayDebugDataForNetLog(capture_mode, debug_data));
  365. return base::Value(std::move(dict));
  366. }
  367. base::Value NetLogSpdyPushPromiseReceivedParams(
  368. const spdy::Http2HeaderBlock* headers,
  369. spdy::SpdyStreamId stream_id,
  370. spdy::SpdyStreamId promised_stream_id,
  371. NetLogCaptureMode capture_mode) {
  372. base::Value::Dict dict;
  373. dict.Set("headers", ElideHttp2HeaderBlockForNetLog(*headers, capture_mode));
  374. dict.Set("id", static_cast<int>(stream_id));
  375. dict.Set("promised_stream_id", static_cast<int>(promised_stream_id));
  376. return base::Value(std::move(dict));
  377. }
  378. base::Value NetLogSpdyAdoptedPushStreamParams(spdy::SpdyStreamId stream_id,
  379. const GURL& url) {
  380. base::Value::Dict dict;
  381. dict.Set("stream_id", static_cast<int>(stream_id));
  382. dict.Set("url", url.spec());
  383. return base::Value(std::move(dict));
  384. }
  385. base::Value NetLogSpdySessionStalledParams(size_t num_active_streams,
  386. size_t num_created_streams,
  387. size_t num_pushed_streams,
  388. size_t max_concurrent_streams,
  389. const std::string& url) {
  390. base::Value::Dict dict;
  391. dict.Set("num_active_streams", static_cast<int>(num_active_streams));
  392. dict.Set("num_created_streams", static_cast<int>(num_created_streams));
  393. dict.Set("num_pushed_streams", static_cast<int>(num_pushed_streams));
  394. dict.Set("max_concurrent_streams", static_cast<int>(max_concurrent_streams));
  395. dict.Set("url", url);
  396. return base::Value(std::move(dict));
  397. }
  398. base::Value NetLogSpdyPriorityParams(spdy::SpdyStreamId stream_id,
  399. spdy::SpdyStreamId parent_stream_id,
  400. int weight,
  401. bool exclusive) {
  402. base::Value::Dict dict;
  403. dict.Set("stream_id", static_cast<int>(stream_id));
  404. dict.Set("parent_stream_id", static_cast<int>(parent_stream_id));
  405. dict.Set("weight", weight);
  406. dict.Set("exclusive", exclusive);
  407. return base::Value(std::move(dict));
  408. }
  409. base::Value NetLogSpdyGreasedFrameParams(spdy::SpdyStreamId stream_id,
  410. uint8_t type,
  411. uint8_t flags,
  412. size_t length,
  413. RequestPriority priority) {
  414. base::Value::Dict dict;
  415. dict.Set("stream_id", static_cast<int>(stream_id));
  416. dict.Set("type", type);
  417. dict.Set("flags", flags);
  418. dict.Set("length", static_cast<int>(length));
  419. dict.Set("priority", RequestPriorityToString(priority));
  420. return base::Value(std::move(dict));
  421. }
  422. // Helper function to return the total size of an array of objects
  423. // with .size() member functions.
  424. template <typename T, size_t N>
  425. size_t GetTotalSize(const T (&arr)[N]) {
  426. size_t total_size = 0;
  427. for (size_t i = 0; i < N; ++i) {
  428. total_size += arr[i].size();
  429. }
  430. return total_size;
  431. }
  432. // Helper class for std:find_if on STL container containing
  433. // SpdyStreamRequest weak pointers.
  434. class RequestEquals {
  435. public:
  436. explicit RequestEquals(const base::WeakPtr<SpdyStreamRequest>& request)
  437. : request_(request) {}
  438. bool operator()(const base::WeakPtr<SpdyStreamRequest>& request) const {
  439. return request_.get() == request.get();
  440. }
  441. private:
  442. const base::WeakPtr<SpdyStreamRequest> request_;
  443. };
  444. // The maximum number of concurrent streams we will ever create. Even if
  445. // the server permits more, we will never exceed this limit.
  446. const size_t kMaxConcurrentStreamLimit = 256;
  447. class SpdyServerPushHelper : public ServerPushDelegate::ServerPushHelper {
  448. public:
  449. explicit SpdyServerPushHelper(base::WeakPtr<SpdySession> session,
  450. const GURL& url)
  451. : session_(session), request_url_(url) {}
  452. void Cancel() override {
  453. if (session_)
  454. session_->CancelPush(request_url_);
  455. }
  456. const GURL& GetURL() const override { return request_url_; }
  457. NetworkIsolationKey GetNetworkIsolationKey() const override {
  458. if (session_) {
  459. return session_->spdy_session_key().network_isolation_key();
  460. }
  461. return NetworkIsolationKey();
  462. }
  463. private:
  464. base::WeakPtr<SpdySession> session_;
  465. const GURL request_url_;
  466. };
  467. } // namespace
  468. SpdyProtocolErrorDetails MapFramerErrorToProtocolError(
  469. http2::Http2DecoderAdapter::SpdyFramerError err) {
  470. switch (err) {
  471. case http2::Http2DecoderAdapter::SPDY_NO_ERROR:
  472. return SPDY_ERROR_NO_ERROR;
  473. case http2::Http2DecoderAdapter::SPDY_INVALID_STREAM_ID:
  474. return SPDY_ERROR_INVALID_STREAM_ID;
  475. case http2::Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME:
  476. return SPDY_ERROR_INVALID_CONTROL_FRAME;
  477. case http2::Http2DecoderAdapter::SPDY_CONTROL_PAYLOAD_TOO_LARGE:
  478. return SPDY_ERROR_CONTROL_PAYLOAD_TOO_LARGE;
  479. case http2::Http2DecoderAdapter::SPDY_DECOMPRESS_FAILURE:
  480. return SPDY_ERROR_DECOMPRESS_FAILURE;
  481. case http2::Http2DecoderAdapter::SPDY_INVALID_PADDING:
  482. return SPDY_ERROR_INVALID_PADDING;
  483. case http2::Http2DecoderAdapter::SPDY_INVALID_DATA_FRAME_FLAGS:
  484. return SPDY_ERROR_INVALID_DATA_FRAME_FLAGS;
  485. case http2::Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME:
  486. return SPDY_ERROR_UNEXPECTED_FRAME;
  487. case http2::Http2DecoderAdapter::SPDY_INTERNAL_FRAMER_ERROR:
  488. return SPDY_ERROR_INTERNAL_FRAMER_ERROR;
  489. case http2::Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE:
  490. return SPDY_ERROR_INVALID_CONTROL_FRAME_SIZE;
  491. case http2::Http2DecoderAdapter::SPDY_OVERSIZED_PAYLOAD:
  492. return SPDY_ERROR_OVERSIZED_PAYLOAD;
  493. case http2::Http2DecoderAdapter::SPDY_HPACK_INDEX_VARINT_ERROR:
  494. return SPDY_ERROR_HPACK_INDEX_VARINT_ERROR;
  495. case http2::Http2DecoderAdapter::SPDY_HPACK_NAME_LENGTH_VARINT_ERROR:
  496. return SPDY_ERROR_HPACK_NAME_LENGTH_VARINT_ERROR;
  497. case http2::Http2DecoderAdapter::SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR:
  498. return SPDY_ERROR_HPACK_VALUE_LENGTH_VARINT_ERROR;
  499. case http2::Http2DecoderAdapter::SPDY_HPACK_NAME_TOO_LONG:
  500. return SPDY_ERROR_HPACK_NAME_TOO_LONG;
  501. case http2::Http2DecoderAdapter::SPDY_HPACK_VALUE_TOO_LONG:
  502. return SPDY_ERROR_HPACK_VALUE_TOO_LONG;
  503. case http2::Http2DecoderAdapter::SPDY_HPACK_NAME_HUFFMAN_ERROR:
  504. return SPDY_ERROR_HPACK_NAME_HUFFMAN_ERROR;
  505. case http2::Http2DecoderAdapter::SPDY_HPACK_VALUE_HUFFMAN_ERROR:
  506. return SPDY_ERROR_HPACK_VALUE_HUFFMAN_ERROR;
  507. case http2::Http2DecoderAdapter::
  508. SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE:
  509. return SPDY_ERROR_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE;
  510. case http2::Http2DecoderAdapter::SPDY_HPACK_INVALID_INDEX:
  511. return SPDY_ERROR_HPACK_INVALID_INDEX;
  512. case http2::Http2DecoderAdapter::SPDY_HPACK_INVALID_NAME_INDEX:
  513. return SPDY_ERROR_HPACK_INVALID_NAME_INDEX;
  514. case http2::Http2DecoderAdapter::
  515. SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED:
  516. return SPDY_ERROR_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED;
  517. case http2::Http2DecoderAdapter::
  518. SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK:
  519. return SPDY_ERROR_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK;
  520. case http2::Http2DecoderAdapter::
  521. SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING:
  522. return SPDY_ERROR_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING;
  523. case http2::Http2DecoderAdapter::SPDY_HPACK_TRUNCATED_BLOCK:
  524. return SPDY_ERROR_HPACK_TRUNCATED_BLOCK;
  525. case http2::Http2DecoderAdapter::SPDY_HPACK_FRAGMENT_TOO_LONG:
  526. return SPDY_ERROR_HPACK_FRAGMENT_TOO_LONG;
  527. case http2::Http2DecoderAdapter::
  528. SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
  529. return SPDY_ERROR_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT;
  530. case http2::Http2DecoderAdapter::SPDY_STOP_PROCESSING:
  531. return SPDY_ERROR_STOP_PROCESSING;
  532. case http2::Http2DecoderAdapter::LAST_ERROR:
  533. NOTREACHED();
  534. }
  535. NOTREACHED();
  536. return static_cast<SpdyProtocolErrorDetails>(-1);
  537. }
  538. Error MapFramerErrorToNetError(
  539. http2::Http2DecoderAdapter::SpdyFramerError err) {
  540. switch (err) {
  541. case http2::Http2DecoderAdapter::SPDY_NO_ERROR:
  542. return OK;
  543. case http2::Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME:
  544. return ERR_HTTP2_PROTOCOL_ERROR;
  545. case http2::Http2DecoderAdapter::SPDY_CONTROL_PAYLOAD_TOO_LARGE:
  546. return ERR_HTTP2_FRAME_SIZE_ERROR;
  547. case http2::Http2DecoderAdapter::SPDY_DECOMPRESS_FAILURE:
  548. case http2::Http2DecoderAdapter::SPDY_HPACK_INDEX_VARINT_ERROR:
  549. case http2::Http2DecoderAdapter::SPDY_HPACK_NAME_LENGTH_VARINT_ERROR:
  550. case http2::Http2DecoderAdapter::SPDY_HPACK_VALUE_LENGTH_VARINT_ERROR:
  551. case http2::Http2DecoderAdapter::SPDY_HPACK_NAME_TOO_LONG:
  552. case http2::Http2DecoderAdapter::SPDY_HPACK_VALUE_TOO_LONG:
  553. case http2::Http2DecoderAdapter::SPDY_HPACK_NAME_HUFFMAN_ERROR:
  554. case http2::Http2DecoderAdapter::SPDY_HPACK_VALUE_HUFFMAN_ERROR:
  555. case http2::Http2DecoderAdapter::
  556. SPDY_HPACK_MISSING_DYNAMIC_TABLE_SIZE_UPDATE:
  557. case http2::Http2DecoderAdapter::SPDY_HPACK_INVALID_INDEX:
  558. case http2::Http2DecoderAdapter::SPDY_HPACK_INVALID_NAME_INDEX:
  559. case http2::Http2DecoderAdapter::
  560. SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_NOT_ALLOWED:
  561. case http2::Http2DecoderAdapter::
  562. SPDY_HPACK_INITIAL_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_LOW_WATER_MARK:
  563. case http2::Http2DecoderAdapter::
  564. SPDY_HPACK_DYNAMIC_TABLE_SIZE_UPDATE_IS_ABOVE_ACKNOWLEDGED_SETTING:
  565. case http2::Http2DecoderAdapter::SPDY_HPACK_TRUNCATED_BLOCK:
  566. case http2::Http2DecoderAdapter::SPDY_HPACK_FRAGMENT_TOO_LONG:
  567. case http2::Http2DecoderAdapter::
  568. SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
  569. return ERR_HTTP2_COMPRESSION_ERROR;
  570. case http2::Http2DecoderAdapter::SPDY_STOP_PROCESSING:
  571. return ERR_HTTP2_COMPRESSION_ERROR;
  572. case http2::Http2DecoderAdapter::SPDY_INVALID_PADDING:
  573. return ERR_HTTP2_PROTOCOL_ERROR;
  574. case http2::Http2DecoderAdapter::SPDY_INVALID_DATA_FRAME_FLAGS:
  575. return ERR_HTTP2_PROTOCOL_ERROR;
  576. case http2::Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME:
  577. return ERR_HTTP2_PROTOCOL_ERROR;
  578. case http2::Http2DecoderAdapter::SPDY_INTERNAL_FRAMER_ERROR:
  579. return ERR_HTTP2_PROTOCOL_ERROR;
  580. case http2::Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE:
  581. return ERR_HTTP2_FRAME_SIZE_ERROR;
  582. case http2::Http2DecoderAdapter::SPDY_INVALID_STREAM_ID:
  583. return ERR_HTTP2_PROTOCOL_ERROR;
  584. case http2::Http2DecoderAdapter::SPDY_OVERSIZED_PAYLOAD:
  585. return ERR_HTTP2_FRAME_SIZE_ERROR;
  586. case http2::Http2DecoderAdapter::LAST_ERROR:
  587. NOTREACHED();
  588. }
  589. NOTREACHED();
  590. return ERR_HTTP2_PROTOCOL_ERROR;
  591. }
  592. SpdyProtocolErrorDetails MapRstStreamStatusToProtocolError(
  593. spdy::SpdyErrorCode error_code) {
  594. switch (error_code) {
  595. case spdy::ERROR_CODE_NO_ERROR:
  596. return STATUS_CODE_NO_ERROR;
  597. case spdy::ERROR_CODE_PROTOCOL_ERROR:
  598. return STATUS_CODE_PROTOCOL_ERROR;
  599. case spdy::ERROR_CODE_INTERNAL_ERROR:
  600. return STATUS_CODE_INTERNAL_ERROR;
  601. case spdy::ERROR_CODE_FLOW_CONTROL_ERROR:
  602. return STATUS_CODE_FLOW_CONTROL_ERROR;
  603. case spdy::ERROR_CODE_SETTINGS_TIMEOUT:
  604. return STATUS_CODE_SETTINGS_TIMEOUT;
  605. case spdy::ERROR_CODE_STREAM_CLOSED:
  606. return STATUS_CODE_STREAM_CLOSED;
  607. case spdy::ERROR_CODE_FRAME_SIZE_ERROR:
  608. return STATUS_CODE_FRAME_SIZE_ERROR;
  609. case spdy::ERROR_CODE_REFUSED_STREAM:
  610. return STATUS_CODE_REFUSED_STREAM;
  611. case spdy::ERROR_CODE_CANCEL:
  612. return STATUS_CODE_CANCEL;
  613. case spdy::ERROR_CODE_COMPRESSION_ERROR:
  614. return STATUS_CODE_COMPRESSION_ERROR;
  615. case spdy::ERROR_CODE_CONNECT_ERROR:
  616. return STATUS_CODE_CONNECT_ERROR;
  617. case spdy::ERROR_CODE_ENHANCE_YOUR_CALM:
  618. return STATUS_CODE_ENHANCE_YOUR_CALM;
  619. case spdy::ERROR_CODE_INADEQUATE_SECURITY:
  620. return STATUS_CODE_INADEQUATE_SECURITY;
  621. case spdy::ERROR_CODE_HTTP_1_1_REQUIRED:
  622. return STATUS_CODE_HTTP_1_1_REQUIRED;
  623. }
  624. NOTREACHED();
  625. return static_cast<SpdyProtocolErrorDetails>(-1);
  626. }
  627. spdy::SpdyErrorCode MapNetErrorToGoAwayStatus(Error err) {
  628. switch (err) {
  629. case OK:
  630. return spdy::ERROR_CODE_NO_ERROR;
  631. case ERR_HTTP2_PROTOCOL_ERROR:
  632. return spdy::ERROR_CODE_PROTOCOL_ERROR;
  633. case ERR_HTTP2_FLOW_CONTROL_ERROR:
  634. return spdy::ERROR_CODE_FLOW_CONTROL_ERROR;
  635. case ERR_HTTP2_FRAME_SIZE_ERROR:
  636. return spdy::ERROR_CODE_FRAME_SIZE_ERROR;
  637. case ERR_HTTP2_COMPRESSION_ERROR:
  638. return spdy::ERROR_CODE_COMPRESSION_ERROR;
  639. case ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY:
  640. return spdy::ERROR_CODE_INADEQUATE_SECURITY;
  641. default:
  642. return spdy::ERROR_CODE_PROTOCOL_ERROR;
  643. }
  644. }
  645. SpdyStreamRequest::SpdyStreamRequest() {
  646. Reset();
  647. }
  648. SpdyStreamRequest::~SpdyStreamRequest() {
  649. CancelRequest();
  650. }
  651. int SpdyStreamRequest::StartRequest(
  652. SpdyStreamType type,
  653. const base::WeakPtr<SpdySession>& session,
  654. const GURL& url,
  655. bool can_send_early,
  656. RequestPriority priority,
  657. const SocketTag& socket_tag,
  658. const NetLogWithSource& net_log,
  659. CompletionOnceCallback callback,
  660. const NetworkTrafficAnnotationTag& traffic_annotation,
  661. bool detect_broken_connection,
  662. base::TimeDelta heartbeat_interval) {
  663. DCHECK(session);
  664. DCHECK(!session_);
  665. DCHECK(!stream_);
  666. DCHECK(callback_.is_null());
  667. DCHECK(url.is_valid()) << url.possibly_invalid_spec();
  668. type_ = type;
  669. session_ = session;
  670. url_ = SimplifyUrlForRequest(url);
  671. priority_ = priority;
  672. socket_tag_ = socket_tag;
  673. net_log_ = net_log;
  674. callback_ = std::move(callback);
  675. traffic_annotation_ = MutableNetworkTrafficAnnotationTag(traffic_annotation);
  676. detect_broken_connection_ = detect_broken_connection;
  677. heartbeat_interval_ = heartbeat_interval;
  678. // If early data is not allowed, confirm the handshake first.
  679. int rv = OK;
  680. if (!can_send_early) {
  681. rv = session_->ConfirmHandshake(
  682. base::BindOnce(&SpdyStreamRequest::OnConfirmHandshakeComplete,
  683. weak_ptr_factory_.GetWeakPtr()));
  684. }
  685. if (rv != OK) {
  686. // If rv is ERR_IO_PENDING, OnConfirmHandshakeComplete() will call
  687. // TryCreateStream() later.
  688. return rv;
  689. }
  690. base::WeakPtr<SpdyStream> stream;
  691. rv = session->TryCreateStream(weak_ptr_factory_.GetWeakPtr(), &stream);
  692. if (rv != OK) {
  693. // If rv is ERR_IO_PENDING, the SpdySession will call
  694. // OnRequestCompleteSuccess() or OnRequestCompleteFailure() later.
  695. return rv;
  696. }
  697. Reset();
  698. stream_ = stream;
  699. return OK;
  700. }
  701. void SpdyStreamRequest::CancelRequest() {
  702. if (session_)
  703. session_->CancelStreamRequest(weak_ptr_factory_.GetWeakPtr());
  704. Reset();
  705. // Do this to cancel any pending CompleteStreamRequest() and
  706. // OnConfirmHandshakeComplete() tasks.
  707. weak_ptr_factory_.InvalidateWeakPtrs();
  708. }
  709. base::WeakPtr<SpdyStream> SpdyStreamRequest::ReleaseStream() {
  710. DCHECK(!session_);
  711. base::WeakPtr<SpdyStream> stream = stream_;
  712. DCHECK(stream);
  713. Reset();
  714. return stream;
  715. }
  716. void SpdyStreamRequest::SetPriority(RequestPriority priority) {
  717. if (priority_ == priority)
  718. return;
  719. if (stream_)
  720. stream_->SetPriority(priority);
  721. if (session_)
  722. session_->ChangeStreamRequestPriority(weak_ptr_factory_.GetWeakPtr(),
  723. priority);
  724. priority_ = priority;
  725. }
  726. void SpdyStreamRequest::OnRequestCompleteSuccess(
  727. const base::WeakPtr<SpdyStream>& stream) {
  728. DCHECK(session_);
  729. DCHECK(!stream_);
  730. DCHECK(!callback_.is_null());
  731. CompletionOnceCallback callback = std::move(callback_);
  732. Reset();
  733. DCHECK(stream);
  734. stream_ = stream;
  735. std::move(callback).Run(OK);
  736. }
  737. void SpdyStreamRequest::OnRequestCompleteFailure(int rv) {
  738. DCHECK(session_);
  739. DCHECK(!stream_);
  740. DCHECK(!callback_.is_null());
  741. CompletionOnceCallback callback = std::move(callback_);
  742. Reset();
  743. DCHECK_NE(rv, OK);
  744. std::move(callback).Run(rv);
  745. }
  746. void SpdyStreamRequest::Reset() {
  747. type_ = SPDY_BIDIRECTIONAL_STREAM;
  748. session_.reset();
  749. stream_.reset();
  750. url_ = GURL();
  751. priority_ = MINIMUM_PRIORITY;
  752. socket_tag_ = SocketTag();
  753. net_log_ = NetLogWithSource();
  754. callback_.Reset();
  755. traffic_annotation_.reset();
  756. }
  757. void SpdyStreamRequest::OnConfirmHandshakeComplete(int rv) {
  758. DCHECK_NE(ERR_IO_PENDING, rv);
  759. if (!session_)
  760. return;
  761. if (rv != OK) {
  762. OnRequestCompleteFailure(rv);
  763. return;
  764. }
  765. // ConfirmHandshake() completed asynchronously. Record the time so the caller
  766. // can adjust LoadTimingInfo.
  767. confirm_handshake_end_ = base::TimeTicks::Now();
  768. if (!session_) {
  769. OnRequestCompleteFailure(ERR_CONNECTION_CLOSED);
  770. return;
  771. }
  772. base::WeakPtr<SpdyStream> stream;
  773. rv = session_->TryCreateStream(weak_ptr_factory_.GetWeakPtr(), &stream);
  774. if (rv == OK) {
  775. OnRequestCompleteSuccess(stream);
  776. } else if (rv != ERR_IO_PENDING) {
  777. // If rv is ERR_IO_PENDING, the SpdySession will call
  778. // OnRequestCompleteSuccess() or OnRequestCompleteFailure() later.
  779. OnRequestCompleteFailure(rv);
  780. }
  781. }
  782. // static
  783. bool SpdySession::CanPool(
  784. TransportSecurityState* transport_security_state,
  785. const SSLInfo& ssl_info,
  786. const SSLConfigService& ssl_config_service,
  787. const std::string& old_hostname,
  788. const std::string& new_hostname,
  789. const net::NetworkIsolationKey& network_isolation_key) {
  790. // Pooling is prohibited if the server cert is not valid for the new domain,
  791. // and for connections on which client certs were sent. It is also prohibited
  792. // when channel ID was sent if the hosts are from different eTLDs+1.
  793. if (IsCertStatusError(ssl_info.cert_status))
  794. return false;
  795. if (ssl_info.client_cert_sent &&
  796. !(ssl_config_service.CanShareConnectionWithClientCerts(old_hostname) &&
  797. ssl_config_service.CanShareConnectionWithClientCerts(new_hostname))) {
  798. return false;
  799. }
  800. if (!ssl_info.cert->VerifyNameMatch(new_hostname))
  801. return false;
  802. std::string pinning_failure_log;
  803. // DISABLE_PIN_REPORTS is set here because this check can fail in
  804. // normal operation without being indicative of a misconfiguration or
  805. // attack. Port is left at 0 as it is never used.
  806. if (transport_security_state->CheckPublicKeyPins(
  807. HostPortPair(new_hostname, 0), ssl_info.is_issued_by_known_root,
  808. ssl_info.public_key_hashes, ssl_info.unverified_cert.get(),
  809. ssl_info.cert.get(), TransportSecurityState::DISABLE_PIN_REPORTS,
  810. network_isolation_key, &pinning_failure_log) ==
  811. TransportSecurityState::PKPStatus::VIOLATED) {
  812. return false;
  813. }
  814. // As with CheckPublicKeyPins above, disable Expect-CT reports.
  815. switch (transport_security_state->CheckCTRequirements(
  816. HostPortPair(new_hostname, 0), ssl_info.is_issued_by_known_root,
  817. ssl_info.public_key_hashes, ssl_info.cert.get(),
  818. ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps,
  819. TransportSecurityState::DISABLE_EXPECT_CT_REPORTS,
  820. ssl_info.ct_policy_compliance, network_isolation_key)) {
  821. case TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
  822. return false;
  823. case TransportSecurityState::CT_REQUIREMENTS_MET:
  824. case TransportSecurityState::CT_NOT_REQUIRED:
  825. // Intentional fallthrough; this case is just here to make sure that all
  826. // possible values of CheckCTRequirements() are handled.
  827. break;
  828. }
  829. return true;
  830. }
  831. SpdySession::SpdySession(
  832. const SpdySessionKey& spdy_session_key,
  833. HttpServerProperties* http_server_properties,
  834. TransportSecurityState* transport_security_state,
  835. SSLConfigService* ssl_config_service,
  836. const quic::ParsedQuicVersionVector& quic_supported_versions,
  837. bool enable_sending_initial_data,
  838. bool enable_ping_based_connection_checking,
  839. bool is_http2_enabled,
  840. bool is_quic_enabled,
  841. size_t session_max_recv_window_size,
  842. int session_max_queued_capped_frames,
  843. const spdy::SettingsMap& initial_settings,
  844. bool enable_http2_settings_grease,
  845. const absl::optional<SpdySessionPool::GreasedHttp2Frame>&
  846. greased_http2_frame,
  847. bool http2_end_stream_with_data_frame,
  848. bool enable_priority_update,
  849. TimeFunc time_func,
  850. ServerPushDelegate* push_delegate,
  851. NetworkQualityEstimator* network_quality_estimator,
  852. NetLog* net_log)
  853. : spdy_session_key_(spdy_session_key),
  854. http_server_properties_(http_server_properties),
  855. transport_security_state_(transport_security_state),
  856. ssl_config_service_(ssl_config_service),
  857. stream_hi_water_mark_(kFirstStreamId),
  858. push_delegate_(push_delegate),
  859. initial_settings_(initial_settings),
  860. enable_http2_settings_grease_(enable_http2_settings_grease),
  861. greased_http2_frame_(greased_http2_frame),
  862. http2_end_stream_with_data_frame_(http2_end_stream_with_data_frame),
  863. enable_priority_update_(enable_priority_update),
  864. max_concurrent_streams_(kInitialMaxConcurrentStreams),
  865. max_concurrent_pushed_streams_(
  866. initial_settings.at(spdy::SETTINGS_MAX_CONCURRENT_STREAMS)),
  867. last_read_time_(time_func()),
  868. session_max_recv_window_size_(session_max_recv_window_size),
  869. session_max_queued_capped_frames_(session_max_queued_capped_frames),
  870. last_recv_window_update_(base::TimeTicks::Now()),
  871. time_to_buffer_small_window_updates_(
  872. kDefaultTimeToBufferSmallWindowUpdates),
  873. stream_initial_send_window_size_(kDefaultInitialWindowSize),
  874. max_header_table_size_(
  875. initial_settings.at(spdy::SETTINGS_HEADER_TABLE_SIZE)),
  876. stream_max_recv_window_size_(
  877. initial_settings.at(spdy::SETTINGS_INITIAL_WINDOW_SIZE)),
  878. net_log_(
  879. NetLogWithSource::Make(net_log, NetLogSourceType::HTTP2_SESSION)),
  880. quic_supported_versions_(quic_supported_versions),
  881. enable_sending_initial_data_(enable_sending_initial_data),
  882. enable_ping_based_connection_checking_(
  883. enable_ping_based_connection_checking),
  884. is_http2_enabled_(is_http2_enabled),
  885. is_quic_enabled_(is_quic_enabled),
  886. enable_push_(IsPushEnabled(initial_settings)),
  887. connection_at_risk_of_loss_time_(
  888. base::Seconds(kDefaultConnectionAtRiskOfLossSeconds)),
  889. hung_interval_(base::Seconds(kHungIntervalSeconds)),
  890. time_func_(time_func),
  891. network_quality_estimator_(network_quality_estimator) {
  892. net_log_.BeginEvent(NetLogEventType::HTTP2_SESSION, [&] {
  893. return NetLogSpdySessionParams(host_port_proxy_pair());
  894. });
  895. DCHECK(base::Contains(initial_settings_, spdy::SETTINGS_HEADER_TABLE_SIZE));
  896. DCHECK(
  897. base::Contains(initial_settings_, spdy::SETTINGS_MAX_CONCURRENT_STREAMS));
  898. DCHECK(base::Contains(initial_settings_, spdy::SETTINGS_INITIAL_WINDOW_SIZE));
  899. if (greased_http2_frame_) {
  900. // See https://tools.ietf.org/html/draft-bishop-httpbis-grease-00
  901. // for reserved frame types.
  902. DCHECK_EQ(0x0b, greased_http2_frame_.value().type % 0x1f);
  903. }
  904. // TODO(mbelshe): consider randomization of the stream_hi_water_mark.
  905. }
  906. SpdySession::~SpdySession() {
  907. CHECK(!in_io_loop_);
  908. DcheckDraining();
  909. DCHECK(waiting_for_confirmation_callbacks_.empty());
  910. DCHECK_EQ(broken_connection_detection_requests_, 0);
  911. // TODO(akalin): Check connection->is_initialized().
  912. DCHECK(socket_);
  913. // With SPDY we can't recycle sockets.
  914. socket_->Disconnect();
  915. RecordHistograms();
  916. net_log_.EndEvent(NetLogEventType::HTTP2_SESSION);
  917. }
  918. int SpdySession::GetPushedStream(const GURL& url,
  919. spdy::SpdyStreamId pushed_stream_id,
  920. RequestPriority priority,
  921. SpdyStream** stream) {
  922. CHECK(!in_io_loop_);
  923. // |pushed_stream_id| must be valid.
  924. DCHECK_NE(pushed_stream_id, kNoPushedStreamFound);
  925. // |pushed_stream_id| must already have been claimed.
  926. DCHECK_NE(pushed_stream_id,
  927. pool_->push_promise_index()->FindStream(url, this));
  928. if (availability_state_ == STATE_DRAINING) {
  929. return ERR_CONNECTION_CLOSED;
  930. }
  931. auto active_it = active_streams_.find(pushed_stream_id);
  932. if (active_it == active_streams_.end()) {
  933. // A previously claimed pushed stream might not be available, for example,
  934. // if the server has reset it in the meanwhile.
  935. return ERR_HTTP2_PUSHED_STREAM_NOT_AVAILABLE;
  936. }
  937. net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_ADOPTED_PUSH_STREAM, [&] {
  938. return NetLogSpdyAdoptedPushStreamParams(pushed_stream_id, url);
  939. });
  940. *stream = active_it->second;
  941. DCHECK_LT(streams_pushed_and_claimed_count_, streams_pushed_count_);
  942. streams_pushed_and_claimed_count_++;
  943. // If the stream is still open, update its priority to that of the request.
  944. if (!(*stream)->IsClosed()) {
  945. (*stream)->SetPriority(priority);
  946. }
  947. return OK;
  948. }
  949. void SpdySession::CancelPush(const GURL& url) {
  950. const spdy::SpdyStreamId stream_id =
  951. pool_->push_promise_index()->FindStream(url, this);
  952. if (stream_id == kNoPushedStreamFound)
  953. return;
  954. DCHECK(IsStreamActive(stream_id));
  955. RecordSpdyPushedStreamFateHistogram(SpdyPushedStreamFate::kAlreadyInCache);
  956. ResetStream(stream_id, ERR_ABORTED, "Cancelled push stream.");
  957. }
  958. void SpdySession::InitializeWithSocketHandle(
  959. std::unique_ptr<ClientSocketHandle> client_socket_handle,
  960. SpdySessionPool* pool) {
  961. DCHECK(!client_socket_handle_);
  962. DCHECK(!owned_stream_socket_);
  963. DCHECK(!socket_);
  964. // TODO(akalin): Check connection->is_initialized() instead. This
  965. // requires re-working CreateFakeSpdySession(), though.
  966. DCHECK(client_socket_handle->socket());
  967. client_socket_handle_ = std::move(client_socket_handle);
  968. socket_ = client_socket_handle_->socket();
  969. client_socket_handle_->AddHigherLayeredPool(this);
  970. InitializeInternal(pool);
  971. }
  972. void SpdySession::InitializeWithSocket(
  973. std::unique_ptr<StreamSocket> stream_socket,
  974. const LoadTimingInfo::ConnectTiming& connect_timing,
  975. SpdySessionPool* pool) {
  976. DCHECK(!client_socket_handle_);
  977. DCHECK(!owned_stream_socket_);
  978. DCHECK(!socket_);
  979. DCHECK(stream_socket);
  980. owned_stream_socket_ = std::move(stream_socket);
  981. socket_ = owned_stream_socket_.get();
  982. connect_timing_ =
  983. std::make_unique<LoadTimingInfo::ConnectTiming>(connect_timing);
  984. InitializeInternal(pool);
  985. }
  986. int SpdySession::ParseAlps() {
  987. auto alps_data = socket_->GetPeerApplicationSettings();
  988. if (!alps_data) {
  989. return OK;
  990. }
  991. AlpsDecoder alps_decoder;
  992. AlpsDecoder::Error error = alps_decoder.Decode(alps_data.value());
  993. base::UmaHistogramEnumeration("Net.SpdySession.AlpsDecoderStatus", error);
  994. if (error != AlpsDecoder::Error::kNoError) {
  995. DoDrainSession(
  996. ERR_HTTP2_PROTOCOL_ERROR,
  997. base::StrCat({"Error parsing ALPS: ",
  998. base::NumberToString(static_cast<int>(error))}));
  999. return ERR_HTTP2_PROTOCOL_ERROR;
  1000. }
  1001. base::UmaHistogramCounts100("Net.SpdySession.AlpsSettingParameterCount",
  1002. alps_decoder.GetSettings().size());
  1003. for (const auto& setting : alps_decoder.GetSettings()) {
  1004. spdy::SpdySettingsId identifier = setting.first;
  1005. uint32_t value = setting.second;
  1006. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_SETTING, [&] {
  1007. return NetLogSpdyRecvSettingParams(identifier, value);
  1008. });
  1009. HandleSetting(identifier, value);
  1010. }
  1011. bool has_valid_entry = false;
  1012. bool has_invalid_entry = false;
  1013. for (const auto& entry : alps_decoder.GetAcceptCh()) {
  1014. const url::SchemeHostPort scheme_host_port(GURL(entry.origin));
  1015. // |entry.origin| must be a valid SchemeHostPort.
  1016. std::string serialized = scheme_host_port.Serialize();
  1017. if (serialized.empty() || entry.origin != serialized) {
  1018. has_invalid_entry = true;
  1019. continue;
  1020. }
  1021. has_valid_entry = true;
  1022. accept_ch_entries_received_via_alps_.insert(
  1023. std::make_pair(std::move(scheme_host_port), entry.value));
  1024. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_ACCEPT_CH,
  1025. [&] { return NetLogSpdyRecvAcceptChParams(entry); });
  1026. }
  1027. SpdyAcceptChEntries value;
  1028. if (has_valid_entry) {
  1029. if (has_invalid_entry) {
  1030. value = SpdyAcceptChEntries::kBothValidAndInvalidEntries;
  1031. } else {
  1032. value = SpdyAcceptChEntries::kOnlyValidEntries;
  1033. }
  1034. } else {
  1035. if (has_invalid_entry) {
  1036. value = SpdyAcceptChEntries::kOnlyInvalidEntries;
  1037. } else {
  1038. value = SpdyAcceptChEntries::kNoEntries;
  1039. }
  1040. }
  1041. base::UmaHistogramEnumeration("Net.SpdySession.AlpsAcceptChEntries", value);
  1042. return OK;
  1043. }
  1044. bool SpdySession::VerifyDomainAuthentication(const std::string& domain) const {
  1045. if (availability_state_ == STATE_DRAINING)
  1046. return false;
  1047. SSLInfo ssl_info;
  1048. if (!GetSSLInfo(&ssl_info))
  1049. return true; // This is not a secure session, so all domains are okay.
  1050. return CanPool(transport_security_state_, ssl_info, *ssl_config_service_,
  1051. host_port_pair().host(), domain,
  1052. spdy_session_key_.network_isolation_key());
  1053. }
  1054. void SpdySession::EnqueueStreamWrite(
  1055. const base::WeakPtr<SpdyStream>& stream,
  1056. spdy::SpdyFrameType frame_type,
  1057. std::unique_ptr<SpdyBufferProducer> producer) {
  1058. DCHECK(frame_type == spdy::SpdyFrameType::HEADERS ||
  1059. frame_type == spdy::SpdyFrameType::DATA);
  1060. EnqueueWrite(stream->priority(), frame_type, std::move(producer), stream,
  1061. stream->traffic_annotation());
  1062. }
  1063. bool SpdySession::GreasedFramesEnabled() const {
  1064. return greased_http2_frame_.has_value();
  1065. }
  1066. void SpdySession::EnqueueGreasedFrame(const base::WeakPtr<SpdyStream>& stream) {
  1067. if (availability_state_ == STATE_DRAINING)
  1068. return;
  1069. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_GREASED_FRAME, [&] {
  1070. return NetLogSpdyGreasedFrameParams(
  1071. stream->stream_id(), greased_http2_frame_.value().type,
  1072. greased_http2_frame_.value().flags,
  1073. greased_http2_frame_.value().payload.length(), stream->priority());
  1074. });
  1075. EnqueueWrite(
  1076. stream->priority(),
  1077. static_cast<spdy::SpdyFrameType>(greased_http2_frame_.value().type),
  1078. std::make_unique<GreasedBufferProducer>(
  1079. stream, &greased_http2_frame_.value(), buffered_spdy_framer_.get()),
  1080. stream, stream->traffic_annotation());
  1081. }
  1082. bool SpdySession::ShouldSendHttp2Priority() const {
  1083. return !enable_priority_update_ || !deprecate_http2_priorities_;
  1084. }
  1085. bool SpdySession::ShouldSendPriorityUpdate() const {
  1086. if (!enable_priority_update_) {
  1087. return false;
  1088. }
  1089. return settings_frame_received_ ? deprecate_http2_priorities_ : true;
  1090. }
  1091. int SpdySession::ConfirmHandshake(CompletionOnceCallback callback) {
  1092. if (availability_state_ == STATE_GOING_AWAY)
  1093. return ERR_FAILED;
  1094. if (availability_state_ == STATE_DRAINING)
  1095. return ERR_CONNECTION_CLOSED;
  1096. int rv = ERR_IO_PENDING;
  1097. if (!in_confirm_handshake_) {
  1098. rv = socket_->ConfirmHandshake(
  1099. base::BindOnce(&SpdySession::NotifyRequestsOfConfirmation,
  1100. weak_factory_.GetWeakPtr()));
  1101. }
  1102. if (rv == ERR_IO_PENDING) {
  1103. in_confirm_handshake_ = true;
  1104. waiting_for_confirmation_callbacks_.push_back(std::move(callback));
  1105. }
  1106. return rv;
  1107. }
  1108. std::unique_ptr<spdy::SpdySerializedFrame> SpdySession::CreateHeaders(
  1109. spdy::SpdyStreamId stream_id,
  1110. RequestPriority priority,
  1111. spdy::SpdyControlFlags flags,
  1112. spdy::Http2HeaderBlock block,
  1113. NetLogSource source_dependency) {
  1114. ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
  1115. CHECK(it != active_streams_.end());
  1116. CHECK_EQ(it->second->stream_id(), stream_id);
  1117. MaybeSendPrefacePing();
  1118. DCHECK(buffered_spdy_framer_.get());
  1119. spdy::SpdyPriority spdy_priority =
  1120. ConvertRequestPriorityToSpdyPriority(priority);
  1121. bool has_priority = true;
  1122. int weight = 0;
  1123. spdy::SpdyStreamId parent_stream_id = 0;
  1124. bool exclusive = false;
  1125. priority_dependency_state_.OnStreamCreation(
  1126. stream_id, spdy_priority, &parent_stream_id, &weight, &exclusive);
  1127. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_HEADERS,
  1128. [&](NetLogCaptureMode capture_mode) {
  1129. return NetLogSpdyHeadersSentParams(
  1130. &block, (flags & spdy::CONTROL_FLAG_FIN) != 0,
  1131. stream_id, has_priority, weight, parent_stream_id,
  1132. exclusive, source_dependency, capture_mode);
  1133. });
  1134. spdy::SpdyHeadersIR headers(stream_id, std::move(block));
  1135. headers.set_has_priority(has_priority);
  1136. headers.set_weight(weight);
  1137. headers.set_parent_stream_id(parent_stream_id);
  1138. headers.set_exclusive(exclusive);
  1139. headers.set_fin((flags & spdy::CONTROL_FLAG_FIN) != 0);
  1140. streams_initiated_count_++;
  1141. return std::make_unique<spdy::SpdySerializedFrame>(
  1142. buffered_spdy_framer_->SerializeFrame(headers));
  1143. }
  1144. std::unique_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(
  1145. spdy::SpdyStreamId stream_id,
  1146. IOBuffer* data,
  1147. int len,
  1148. spdy::SpdyDataFlags flags,
  1149. int* effective_len,
  1150. bool* end_stream) {
  1151. if (availability_state_ == STATE_DRAINING) {
  1152. return nullptr;
  1153. }
  1154. ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
  1155. CHECK(it != active_streams_.end());
  1156. SpdyStream* stream = it->second;
  1157. CHECK_EQ(stream->stream_id(), stream_id);
  1158. if (len < 0) {
  1159. NOTREACHED();
  1160. return nullptr;
  1161. }
  1162. *effective_len = std::min(len, kMaxSpdyFrameChunkSize);
  1163. bool send_stalled_by_stream = (stream->send_window_size() <= 0);
  1164. bool send_stalled_by_session = IsSendStalled();
  1165. // NOTE: There's an enum of the same name in histograms.xml.
  1166. enum SpdyFrameFlowControlState {
  1167. SEND_NOT_STALLED,
  1168. SEND_STALLED_BY_STREAM,
  1169. SEND_STALLED_BY_SESSION,
  1170. SEND_STALLED_BY_STREAM_AND_SESSION,
  1171. };
  1172. SpdyFrameFlowControlState frame_flow_control_state = SEND_NOT_STALLED;
  1173. if (send_stalled_by_stream) {
  1174. if (send_stalled_by_session) {
  1175. frame_flow_control_state = SEND_STALLED_BY_STREAM_AND_SESSION;
  1176. } else {
  1177. frame_flow_control_state = SEND_STALLED_BY_STREAM;
  1178. }
  1179. } else if (send_stalled_by_session) {
  1180. frame_flow_control_state = SEND_STALLED_BY_SESSION;
  1181. }
  1182. UMA_HISTOGRAM_ENUMERATION("Net.SpdyFrameStreamAndSessionFlowControlState",
  1183. frame_flow_control_state,
  1184. SEND_STALLED_BY_STREAM_AND_SESSION + 1);
  1185. // Obey send window size of the stream.
  1186. if (send_stalled_by_stream) {
  1187. stream->set_send_stalled_by_flow_control(true);
  1188. // Even though we're currently stalled only by the stream, we
  1189. // might end up being stalled by the session also.
  1190. QueueSendStalledStream(*stream);
  1191. net_log_.AddEventWithIntParams(
  1192. NetLogEventType::HTTP2_SESSION_STREAM_STALLED_BY_STREAM_SEND_WINDOW,
  1193. "stream_id", stream_id);
  1194. return nullptr;
  1195. }
  1196. *effective_len = std::min(*effective_len, stream->send_window_size());
  1197. // Obey send window size of the session.
  1198. if (send_stalled_by_session) {
  1199. stream->set_send_stalled_by_flow_control(true);
  1200. QueueSendStalledStream(*stream);
  1201. net_log_.AddEventWithIntParams(
  1202. NetLogEventType::HTTP2_SESSION_STREAM_STALLED_BY_SESSION_SEND_WINDOW,
  1203. "stream_id", stream_id);
  1204. return nullptr;
  1205. }
  1206. *effective_len = std::min(*effective_len, session_send_window_size_);
  1207. DCHECK_GE(*effective_len, 0);
  1208. // Clear FIN flag if only some of the data will be in the data
  1209. // frame.
  1210. if (*effective_len < len)
  1211. flags = static_cast<spdy::SpdyDataFlags>(flags & ~spdy::DATA_FLAG_FIN);
  1212. // Send PrefacePing for DATA_FRAMEs with nonzero payload size.
  1213. if (*effective_len > 0)
  1214. MaybeSendPrefacePing();
  1215. // TODO(mbelshe): reduce memory copies here.
  1216. DCHECK(buffered_spdy_framer_.get());
  1217. std::unique_ptr<spdy::SpdySerializedFrame> frame(
  1218. buffered_spdy_framer_->CreateDataFrame(
  1219. stream_id, data->data(), static_cast<uint32_t>(*effective_len),
  1220. flags));
  1221. auto data_buffer = std::make_unique<SpdyBuffer>(std::move(frame));
  1222. // Send window size is based on payload size, so nothing to do if this is
  1223. // just a FIN with no payload.
  1224. if (*effective_len != 0) {
  1225. DecreaseSendWindowSize(static_cast<int32_t>(*effective_len));
  1226. data_buffer->AddConsumeCallback(base::BindRepeating(
  1227. &SpdySession::OnWriteBufferConsumed, weak_factory_.GetWeakPtr(),
  1228. static_cast<size_t>(*effective_len)));
  1229. }
  1230. *end_stream = (flags & spdy::DATA_FLAG_FIN) == spdy::DATA_FLAG_FIN;
  1231. return data_buffer;
  1232. }
  1233. void SpdySession::UpdateStreamPriority(SpdyStream* stream,
  1234. RequestPriority old_priority,
  1235. RequestPriority new_priority) {
  1236. // There might be write frames enqueued for |stream| regardless of whether it
  1237. // is active (stream_id != 0) or inactive (no HEADERS frame has been sent out
  1238. // yet and stream_id == 0).
  1239. write_queue_.ChangePriorityOfWritesForStream(stream, old_priority,
  1240. new_priority);
  1241. // PRIORITY frames only need to be sent if |stream| is active.
  1242. const spdy::SpdyStreamId stream_id = stream->stream_id();
  1243. if (stream_id == 0)
  1244. return;
  1245. DCHECK(IsStreamActive(stream_id));
  1246. if (base::FeatureList::IsEnabled(features::kAvoidH2Reprioritization))
  1247. return;
  1248. auto updates = priority_dependency_state_.OnStreamUpdate(
  1249. stream_id, ConvertRequestPriorityToSpdyPriority(new_priority));
  1250. for (auto u : updates) {
  1251. DCHECK(IsStreamActive(u.id));
  1252. EnqueuePriorityFrame(u.id, u.parent_stream_id, u.weight, u.exclusive);
  1253. }
  1254. }
  1255. void SpdySession::CloseActiveStream(spdy::SpdyStreamId stream_id, int status) {
  1256. DCHECK_NE(stream_id, 0u);
  1257. auto it = active_streams_.find(stream_id);
  1258. if (it == active_streams_.end()) {
  1259. NOTREACHED();
  1260. return;
  1261. }
  1262. CloseActiveStreamIterator(it, status);
  1263. }
  1264. void SpdySession::CloseCreatedStream(const base::WeakPtr<SpdyStream>& stream,
  1265. int status) {
  1266. DCHECK_EQ(stream->stream_id(), 0u);
  1267. auto it = created_streams_.find(stream.get());
  1268. if (it == created_streams_.end()) {
  1269. NOTREACHED();
  1270. return;
  1271. }
  1272. CloseCreatedStreamIterator(it, status);
  1273. }
  1274. void SpdySession::ResetStream(spdy::SpdyStreamId stream_id,
  1275. int error,
  1276. const std::string& description) {
  1277. DCHECK_NE(stream_id, 0u);
  1278. auto it = active_streams_.find(stream_id);
  1279. if (it == active_streams_.end()) {
  1280. NOTREACHED();
  1281. return;
  1282. }
  1283. ResetStreamIterator(it, error, description);
  1284. }
  1285. bool SpdySession::IsStreamActive(spdy::SpdyStreamId stream_id) const {
  1286. return base::Contains(active_streams_, stream_id);
  1287. }
  1288. LoadState SpdySession::GetLoadState() const {
  1289. // Just report that we're idle since the session could be doing
  1290. // many things concurrently.
  1291. return LOAD_STATE_IDLE;
  1292. }
  1293. int SpdySession::GetRemoteEndpoint(IPEndPoint* endpoint) {
  1294. return GetPeerAddress(endpoint);
  1295. }
  1296. bool SpdySession::GetSSLInfo(SSLInfo* ssl_info) const {
  1297. return socket_->GetSSLInfo(ssl_info);
  1298. }
  1299. base::StringPiece SpdySession::GetAcceptChViaAlps(
  1300. const url::SchemeHostPort& scheme_host_port) const {
  1301. auto it = accept_ch_entries_received_via_alps_.find(scheme_host_port);
  1302. if (it == accept_ch_entries_received_via_alps_.end()) {
  1303. LogSpdyAcceptChForOriginHistogram(false);
  1304. return {};
  1305. }
  1306. LogSpdyAcceptChForOriginHistogram(true);
  1307. return it->second;
  1308. }
  1309. bool SpdySession::WasAlpnNegotiated() const {
  1310. return socket_->WasAlpnNegotiated();
  1311. }
  1312. NextProto SpdySession::GetNegotiatedProtocol() const {
  1313. return socket_->GetNegotiatedProtocol();
  1314. }
  1315. void SpdySession::SendStreamWindowUpdate(spdy::SpdyStreamId stream_id,
  1316. uint32_t delta_window_size) {
  1317. ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
  1318. CHECK(it != active_streams_.end());
  1319. CHECK_EQ(it->second->stream_id(), stream_id);
  1320. SendWindowUpdateFrame(stream_id, delta_window_size, it->second->priority());
  1321. }
  1322. void SpdySession::CloseSessionOnError(Error err,
  1323. const std::string& description) {
  1324. DCHECK_LT(err, ERR_IO_PENDING);
  1325. DoDrainSession(err, description);
  1326. }
  1327. void SpdySession::MakeUnavailable() {
  1328. if (availability_state_ == STATE_AVAILABLE) {
  1329. availability_state_ = STATE_GOING_AWAY;
  1330. pool_->MakeSessionUnavailable(GetWeakPtr());
  1331. }
  1332. }
  1333. void SpdySession::StartGoingAway(spdy::SpdyStreamId last_good_stream_id,
  1334. Error status) {
  1335. DCHECK_GE(availability_state_, STATE_GOING_AWAY);
  1336. DCHECK_NE(OK, status);
  1337. DCHECK_NE(ERR_IO_PENDING, status);
  1338. // The loops below are carefully written to avoid reentrancy problems.
  1339. NotifyRequestsOfConfirmation(status);
  1340. while (true) {
  1341. size_t old_size = GetTotalSize(pending_create_stream_queues_);
  1342. base::WeakPtr<SpdyStreamRequest> pending_request =
  1343. GetNextPendingStreamRequest();
  1344. if (!pending_request)
  1345. break;
  1346. // No new stream requests should be added while the session is
  1347. // going away.
  1348. DCHECK_GT(old_size, GetTotalSize(pending_create_stream_queues_));
  1349. pending_request->OnRequestCompleteFailure(status);
  1350. }
  1351. while (true) {
  1352. size_t old_size = active_streams_.size();
  1353. auto it = active_streams_.lower_bound(last_good_stream_id + 1);
  1354. if (it == active_streams_.end())
  1355. break;
  1356. LogAbandonedActiveStream(it, status);
  1357. CloseActiveStreamIterator(it, status);
  1358. // No new streams should be activated while the session is going
  1359. // away.
  1360. DCHECK_GT(old_size, active_streams_.size());
  1361. }
  1362. while (!created_streams_.empty()) {
  1363. size_t old_size = created_streams_.size();
  1364. auto it = created_streams_.begin();
  1365. LogAbandonedStream(*it, status);
  1366. CloseCreatedStreamIterator(it, status);
  1367. // No new streams should be created while the session is going
  1368. // away.
  1369. DCHECK_GT(old_size, created_streams_.size());
  1370. }
  1371. write_queue_.RemovePendingWritesForStreamsAfter(last_good_stream_id);
  1372. DcheckGoingAway();
  1373. MaybeFinishGoingAway();
  1374. }
  1375. void SpdySession::MaybeFinishGoingAway() {
  1376. if (active_streams_.empty() && created_streams_.empty() &&
  1377. availability_state_ == STATE_GOING_AWAY) {
  1378. DoDrainSession(OK, "Finished going away");
  1379. }
  1380. }
  1381. base::Value SpdySession::GetInfoAsValue() const {
  1382. base::Value::Dict dict;
  1383. dict.Set("source_id", static_cast<int>(net_log_.source().id));
  1384. dict.Set("host_port_pair", host_port_pair().ToString());
  1385. if (!pooled_aliases_.empty()) {
  1386. base::Value::List alias_list;
  1387. for (const auto& alias : pooled_aliases_) {
  1388. alias_list.Append(alias.host_port_pair().ToString());
  1389. }
  1390. dict.Set("aliases", std::move(alias_list));
  1391. }
  1392. dict.Set("proxy", ProxyServerToProxyUri(host_port_proxy_pair().second));
  1393. dict.Set("network_isolation_key",
  1394. spdy_session_key_.network_isolation_key().ToDebugString());
  1395. dict.Set("active_streams", static_cast<int>(active_streams_.size()));
  1396. dict.Set("unclaimed_pushed_streams",
  1397. static_cast<int>(
  1398. pool_->push_promise_index()->CountStreamsForSession(this)));
  1399. dict.Set("negotiated_protocol",
  1400. NextProtoToString(socket_->GetNegotiatedProtocol()));
  1401. dict.Set("error", error_on_close_);
  1402. dict.Set("max_concurrent_streams", static_cast<int>(max_concurrent_streams_));
  1403. dict.Set("streams_initiated_count", streams_initiated_count_);
  1404. dict.Set("streams_pushed_count", streams_pushed_count_);
  1405. dict.Set("streams_pushed_and_claimed_count",
  1406. streams_pushed_and_claimed_count_);
  1407. dict.Set("streams_abandoned_count", streams_abandoned_count_);
  1408. DCHECK(buffered_spdy_framer_.get());
  1409. dict.Set("frames_received", buffered_spdy_framer_->frames_received());
  1410. dict.Set("send_window_size", session_send_window_size_);
  1411. dict.Set("recv_window_size", session_recv_window_size_);
  1412. dict.Set("unacked_recv_window_bytes", session_unacked_recv_window_bytes_);
  1413. return base::Value(std::move(dict));
  1414. }
  1415. bool SpdySession::IsReused() const {
  1416. if (buffered_spdy_framer_->frames_received() > 0)
  1417. return true;
  1418. // If there's no socket pool in use (i.e., |owned_stream_socket_| is
  1419. // non-null), then the SpdySession could only have been created with freshly
  1420. // connected socket, since canceling the H2 session request would have
  1421. // destroyed the socket.
  1422. return owned_stream_socket_ ||
  1423. client_socket_handle_->reuse_type() == ClientSocketHandle::UNUSED_IDLE;
  1424. }
  1425. bool SpdySession::GetLoadTimingInfo(spdy::SpdyStreamId stream_id,
  1426. LoadTimingInfo* load_timing_info) const {
  1427. if (client_socket_handle_) {
  1428. DCHECK(!connect_timing_);
  1429. return client_socket_handle_->GetLoadTimingInfo(stream_id != kFirstStreamId,
  1430. load_timing_info);
  1431. }
  1432. DCHECK(connect_timing_);
  1433. DCHECK(socket_);
  1434. // The socket is considered "fresh" (not reused) only for the first stream on
  1435. // a SPDY session. All others consider it reused, and don't return connection
  1436. // establishment timing information.
  1437. load_timing_info->socket_reused = (stream_id != kFirstStreamId);
  1438. if (!load_timing_info->socket_reused)
  1439. load_timing_info->connect_timing = *connect_timing_;
  1440. load_timing_info->socket_log_id = socket_->NetLog().source().id;
  1441. return true;
  1442. }
  1443. int SpdySession::GetPeerAddress(IPEndPoint* address) const {
  1444. if (socket_)
  1445. return socket_->GetPeerAddress(address);
  1446. return ERR_SOCKET_NOT_CONNECTED;
  1447. }
  1448. int SpdySession::GetLocalAddress(IPEndPoint* address) const {
  1449. if (socket_)
  1450. return socket_->GetLocalAddress(address);
  1451. return ERR_SOCKET_NOT_CONNECTED;
  1452. }
  1453. void SpdySession::AddPooledAlias(const SpdySessionKey& alias_key) {
  1454. pooled_aliases_.insert(alias_key);
  1455. }
  1456. void SpdySession::RemovePooledAlias(const SpdySessionKey& alias_key) {
  1457. pooled_aliases_.erase(alias_key);
  1458. }
  1459. bool SpdySession::HasAcceptableTransportSecurity() const {
  1460. SSLInfo ssl_info;
  1461. CHECK(GetSSLInfo(&ssl_info));
  1462. // HTTP/2 requires TLS 1.2+
  1463. if (SSLConnectionStatusToVersion(ssl_info.connection_status) <
  1464. SSL_CONNECTION_VERSION_TLS1_2) {
  1465. return false;
  1466. }
  1467. if (!IsTLSCipherSuiteAllowedByHTTP2(
  1468. SSLConnectionStatusToCipherSuite(ssl_info.connection_status))) {
  1469. return false;
  1470. }
  1471. return true;
  1472. }
  1473. base::WeakPtr<SpdySession> SpdySession::GetWeakPtr() {
  1474. return weak_factory_.GetWeakPtr();
  1475. }
  1476. bool SpdySession::CloseOneIdleConnection() {
  1477. CHECK(!in_io_loop_);
  1478. DCHECK(pool_);
  1479. if (active_streams_.empty()) {
  1480. DoDrainSession(ERR_CONNECTION_CLOSED, "Closing idle connection.");
  1481. }
  1482. // Return false as the socket wasn't immediately closed.
  1483. return false;
  1484. }
  1485. bool SpdySession::ValidatePushedStream(spdy::SpdyStreamId stream_id,
  1486. const GURL& url,
  1487. const HttpRequestInfo& request_info,
  1488. const SpdySessionKey& key) const {
  1489. SpdySessionKey::CompareForAliasingResult compare_result =
  1490. key.CompareForAliasing(spdy_session_key_);
  1491. // Keys must be aliasable. This code does not support changing the tag of live
  1492. // sessions, so just fail on a socket tag mismatch.
  1493. if (!compare_result.is_potentially_aliasable ||
  1494. !compare_result.is_socket_tag_match) {
  1495. return false;
  1496. }
  1497. // Certificate must match for encrypted schemes only.
  1498. if (key != spdy_session_key_ && url.SchemeIsCryptographic() &&
  1499. !VerifyDomainAuthentication(key.host_port_pair().host())) {
  1500. return false;
  1501. }
  1502. auto stream_it = active_streams_.find(stream_id);
  1503. if (stream_it == active_streams_.end()) {
  1504. // Only active streams should be in Http2PushPromiseIndex.
  1505. NOTREACHED();
  1506. return false;
  1507. }
  1508. const spdy::Http2HeaderBlock& request_headers =
  1509. stream_it->second->request_headers();
  1510. spdy::Http2HeaderBlock::const_iterator method_it =
  1511. request_headers.find(spdy::kHttp2MethodHeader);
  1512. if (method_it == request_headers.end()) {
  1513. // TryCreatePushStream() would have reset the stream if it had no method.
  1514. NOTREACHED();
  1515. return false;
  1516. }
  1517. // Request method must match.
  1518. if (request_info.method != method_it->second) {
  1519. return false;
  1520. }
  1521. return true;
  1522. }
  1523. base::WeakPtr<SpdySession> SpdySession::GetWeakPtrToSession() {
  1524. return GetWeakPtr();
  1525. }
  1526. bool SpdySession::ChangeSocketTag(const SocketTag& new_tag) {
  1527. if (!IsAvailable() || !socket_)
  1528. return false;
  1529. // Changing the tag on the underlying socket will affect all streams,
  1530. // so only allow changing the tag when there are no active streams.
  1531. if (is_active())
  1532. return false;
  1533. socket_->ApplySocketTag(new_tag);
  1534. SpdySessionKey new_key(
  1535. spdy_session_key_.host_port_pair(), spdy_session_key_.proxy_server(),
  1536. spdy_session_key_.privacy_mode(), spdy_session_key_.is_proxy_session(),
  1537. new_tag, spdy_session_key_.network_isolation_key(),
  1538. spdy_session_key_.secure_dns_policy());
  1539. spdy_session_key_ = new_key;
  1540. return true;
  1541. }
  1542. void SpdySession::EnableBrokenConnectionDetection(
  1543. base::TimeDelta heartbeat_interval) {
  1544. DCHECK_GE(broken_connection_detection_requests_, 0);
  1545. if (broken_connection_detection_requests_++ > 0)
  1546. return;
  1547. DCHECK(!IsBrokenConnectionDetectionEnabled());
  1548. NetworkChangeNotifier::AddDefaultNetworkActiveObserver(this);
  1549. heartbeat_interval_ = heartbeat_interval;
  1550. heartbeat_timer_.Start(
  1551. FROM_HERE, heartbeat_interval_,
  1552. base::BindOnce(&SpdySession::MaybeCheckConnectionStatus,
  1553. weak_factory_.GetWeakPtr()));
  1554. }
  1555. bool SpdySession::IsBrokenConnectionDetectionEnabled() const {
  1556. return heartbeat_timer_.IsRunning();
  1557. }
  1558. // static
  1559. void SpdySession::RecordSpdyPushedStreamFateHistogram(
  1560. SpdyPushedStreamFate value) {
  1561. UMA_HISTOGRAM_ENUMERATION("Net.SpdyPushedStreamFate", value);
  1562. }
  1563. void SpdySession::InitializeInternal(SpdySessionPool* pool) {
  1564. CHECK(!in_io_loop_);
  1565. DCHECK_EQ(availability_state_, STATE_AVAILABLE);
  1566. DCHECK_EQ(read_state_, READ_STATE_DO_READ);
  1567. DCHECK_EQ(write_state_, WRITE_STATE_IDLE);
  1568. session_send_window_size_ = kDefaultInitialWindowSize;
  1569. session_recv_window_size_ = kDefaultInitialWindowSize;
  1570. buffered_spdy_framer_ = std::make_unique<BufferedSpdyFramer>(
  1571. initial_settings_.find(spdy::SETTINGS_MAX_HEADER_LIST_SIZE)->second,
  1572. net_log_, time_func_);
  1573. buffered_spdy_framer_->set_visitor(this);
  1574. buffered_spdy_framer_->set_debug_visitor(this);
  1575. buffered_spdy_framer_->UpdateHeaderDecoderTableSize(max_header_table_size_);
  1576. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_INITIALIZED, [&] {
  1577. return NetLogSpdyInitializedParams(socket_->NetLog().source());
  1578. });
  1579. DCHECK_EQ(availability_state_, STATE_AVAILABLE);
  1580. if (enable_sending_initial_data_)
  1581. SendInitialData();
  1582. pool_ = pool;
  1583. // Bootstrap the read loop.
  1584. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1585. FROM_HERE,
  1586. base::BindOnce(&SpdySession::PumpReadLoop, weak_factory_.GetWeakPtr(),
  1587. READ_STATE_DO_READ, OK));
  1588. }
  1589. // {,Try}CreateStream() can be called with |in_io_loop_| set if a stream is
  1590. // being created in response to another being closed due to received data.
  1591. int SpdySession::TryCreateStream(
  1592. const base::WeakPtr<SpdyStreamRequest>& request,
  1593. base::WeakPtr<SpdyStream>* stream) {
  1594. DCHECK(request);
  1595. if (availability_state_ == STATE_GOING_AWAY)
  1596. return ERR_FAILED;
  1597. if (availability_state_ == STATE_DRAINING)
  1598. return ERR_CONNECTION_CLOSED;
  1599. // Fail if ChangeSocketTag() has been called.
  1600. if (request->socket_tag_ != spdy_session_key_.socket_tag())
  1601. return ERR_FAILED;
  1602. if ((active_streams_.size() + created_streams_.size() - num_pushed_streams_ <
  1603. max_concurrent_streams_)) {
  1604. return CreateStream(*request, stream);
  1605. }
  1606. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_STALLED_MAX_STREAMS, [&] {
  1607. return NetLogSpdySessionStalledParams(
  1608. active_streams_.size(), created_streams_.size(), num_pushed_streams_,
  1609. max_concurrent_streams_, request->url().spec());
  1610. });
  1611. RequestPriority priority = request->priority();
  1612. CHECK_GE(priority, MINIMUM_PRIORITY);
  1613. CHECK_LE(priority, MAXIMUM_PRIORITY);
  1614. pending_create_stream_queues_[priority].push_back(request);
  1615. return ERR_IO_PENDING;
  1616. }
  1617. int SpdySession::CreateStream(const SpdyStreamRequest& request,
  1618. base::WeakPtr<SpdyStream>* stream) {
  1619. DCHECK_GE(request.priority(), MINIMUM_PRIORITY);
  1620. DCHECK_LE(request.priority(), MAXIMUM_PRIORITY);
  1621. if (availability_state_ == STATE_GOING_AWAY)
  1622. return ERR_FAILED;
  1623. if (availability_state_ == STATE_DRAINING)
  1624. return ERR_CONNECTION_CLOSED;
  1625. DCHECK(socket_);
  1626. UMA_HISTOGRAM_BOOLEAN("Net.SpdySession.CreateStreamWithSocketConnected",
  1627. socket_->IsConnected());
  1628. if (!socket_->IsConnected()) {
  1629. DoDrainSession(
  1630. ERR_CONNECTION_CLOSED,
  1631. "Tried to create SPDY stream for a closed socket connection.");
  1632. return ERR_CONNECTION_CLOSED;
  1633. }
  1634. auto new_stream = std::make_unique<SpdyStream>(
  1635. request.type(), GetWeakPtr(), request.url(), request.priority(),
  1636. stream_initial_send_window_size_, stream_max_recv_window_size_,
  1637. request.net_log(), request.traffic_annotation(),
  1638. request.detect_broken_connection_);
  1639. *stream = new_stream->GetWeakPtr();
  1640. InsertCreatedStream(std::move(new_stream));
  1641. if (request.detect_broken_connection_)
  1642. EnableBrokenConnectionDetection(request.heartbeat_interval_);
  1643. return OK;
  1644. }
  1645. bool SpdySession::CancelStreamRequest(
  1646. const base::WeakPtr<SpdyStreamRequest>& request) {
  1647. DCHECK(request);
  1648. RequestPriority priority = request->priority();
  1649. CHECK_GE(priority, MINIMUM_PRIORITY);
  1650. CHECK_LE(priority, MAXIMUM_PRIORITY);
  1651. #if DCHECK_IS_ON()
  1652. // |request| should not be in a queue not matching its priority.
  1653. for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
  1654. if (priority == i)
  1655. continue;
  1656. PendingStreamRequestQueue* queue = &pending_create_stream_queues_[i];
  1657. DCHECK(std::find_if(queue->begin(), queue->end(), RequestEquals(request)) ==
  1658. queue->end());
  1659. }
  1660. #endif
  1661. PendingStreamRequestQueue* queue = &pending_create_stream_queues_[priority];
  1662. // Remove |request| from |queue| while preserving the order of the
  1663. // other elements.
  1664. PendingStreamRequestQueue::iterator it =
  1665. std::find_if(queue->begin(), queue->end(), RequestEquals(request));
  1666. // The request may already be removed if there's a
  1667. // CompleteStreamRequest() in flight.
  1668. if (it != queue->end()) {
  1669. it = queue->erase(it);
  1670. // |request| should be in the queue at most once, and if it is
  1671. // present, should not be pending completion.
  1672. DCHECK(std::find_if(it, queue->end(), RequestEquals(request)) ==
  1673. queue->end());
  1674. return true;
  1675. }
  1676. return false;
  1677. }
  1678. void SpdySession::ChangeStreamRequestPriority(
  1679. const base::WeakPtr<SpdyStreamRequest>& request,
  1680. RequestPriority priority) {
  1681. // |request->priority()| is updated by the caller after this returns.
  1682. // |request| needs to still have its old priority in order for
  1683. // CancelStreamRequest() to find it in the correct queue.
  1684. DCHECK_NE(priority, request->priority());
  1685. if (CancelStreamRequest(request)) {
  1686. pending_create_stream_queues_[priority].push_back(request);
  1687. }
  1688. }
  1689. base::WeakPtr<SpdyStreamRequest> SpdySession::GetNextPendingStreamRequest() {
  1690. for (int j = MAXIMUM_PRIORITY; j >= MINIMUM_PRIORITY; --j) {
  1691. if (pending_create_stream_queues_[j].empty())
  1692. continue;
  1693. base::WeakPtr<SpdyStreamRequest> pending_request =
  1694. pending_create_stream_queues_[j].front();
  1695. DCHECK(pending_request);
  1696. pending_create_stream_queues_[j].pop_front();
  1697. return pending_request;
  1698. }
  1699. return base::WeakPtr<SpdyStreamRequest>();
  1700. }
  1701. void SpdySession::ProcessPendingStreamRequests() {
  1702. size_t max_requests_to_process =
  1703. max_concurrent_streams_ -
  1704. (active_streams_.size() + created_streams_.size());
  1705. for (size_t i = 0; i < max_requests_to_process; ++i) {
  1706. base::WeakPtr<SpdyStreamRequest> pending_request =
  1707. GetNextPendingStreamRequest();
  1708. if (!pending_request)
  1709. break;
  1710. // Note that this post can race with other stream creations, and it's
  1711. // possible that the un-stalled stream will be stalled again if it loses.
  1712. // TODO(jgraettinger): Provide stronger ordering guarantees.
  1713. base::ThreadTaskRunnerHandle::Get()->PostTask(
  1714. FROM_HERE, base::BindOnce(&SpdySession::CompleteStreamRequest,
  1715. weak_factory_.GetWeakPtr(), pending_request));
  1716. }
  1717. }
  1718. void SpdySession::TryCreatePushStream(spdy::SpdyStreamId stream_id,
  1719. spdy::SpdyStreamId associated_stream_id,
  1720. spdy::Http2HeaderBlock headers) {
  1721. // Pushed streams are speculative, so they start at an IDLE priority.
  1722. // TODO(bnc): Send pushed stream cancellation with higher priority to avoid
  1723. // wasting bandwidth.
  1724. const RequestPriority request_priority = IDLE;
  1725. if (!enable_push_) {
  1726. RecordSpdyPushedStreamFateHistogram(SpdyPushedStreamFate::kPushDisabled);
  1727. EnqueueResetStreamFrame(stream_id, request_priority,
  1728. spdy::ERROR_CODE_REFUSED_STREAM,
  1729. "Push is disabled.");
  1730. return;
  1731. }
  1732. if ((stream_id & 0x1) != 0) {
  1733. std::string description = base::StringPrintf(
  1734. "Received invalid pushed stream id %d (must be even) on stream id %d.",
  1735. stream_id, associated_stream_id);
  1736. LOG(WARNING) << description;
  1737. RecordSpdyPushedStreamFateHistogram(
  1738. SpdyPushedStreamFate::kPromisedStreamIdParityError);
  1739. CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, description);
  1740. return;
  1741. }
  1742. if ((associated_stream_id & 0x1) != 1) {
  1743. std::string description = base::StringPrintf(
  1744. "Received pushed stream id %d on invalid stream id %d (must be odd).",
  1745. stream_id, associated_stream_id);
  1746. LOG(WARNING) << description;
  1747. RecordSpdyPushedStreamFateHistogram(
  1748. SpdyPushedStreamFate::kAssociatedStreamIdParityError);
  1749. CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, description);
  1750. return;
  1751. }
  1752. if (stream_id <= last_accepted_push_stream_id_) {
  1753. std::string description = base::StringPrintf(
  1754. "Received pushed stream id %d must be larger than last accepted id %d.",
  1755. stream_id, last_accepted_push_stream_id_);
  1756. LOG(WARNING) << description;
  1757. RecordSpdyPushedStreamFateHistogram(
  1758. SpdyPushedStreamFate::kStreamIdOutOfOrder);
  1759. CloseSessionOnError(ERR_HTTP2_PROTOCOL_ERROR, description);
  1760. return;
  1761. }
  1762. // |last_accepted_push_stream_id_| check above guarantees that this stream has
  1763. // not been activated yet.
  1764. DCHECK(!IsStreamActive(stream_id));
  1765. last_accepted_push_stream_id_ = stream_id;
  1766. if (availability_state_ == STATE_GOING_AWAY) {
  1767. RecordSpdyPushedStreamFateHistogram(SpdyPushedStreamFate::kGoingAway);
  1768. EnqueueResetStreamFrame(stream_id, request_priority,
  1769. spdy::ERROR_CODE_REFUSED_STREAM,
  1770. "Push stream request received while going away.");
  1771. return;
  1772. }
  1773. streams_pushed_count_++;
  1774. // Verify that the response had a URL for us.
  1775. GURL gurl(quic::SpdyServerPushUtils::GetPromisedUrlFromHeaders(headers));
  1776. if (!gurl.is_valid()) {
  1777. RecordSpdyPushedStreamFateHistogram(SpdyPushedStreamFate::kInvalidUrl);
  1778. EnqueueResetStreamFrame(stream_id, request_priority,
  1779. spdy::ERROR_CODE_REFUSED_STREAM,
  1780. "Invalid pushed request headers.");
  1781. return;
  1782. }
  1783. // GetPromisedUrlFromHeaders() guarantees that the scheme is http or https.
  1784. DCHECK(gurl.SchemeIs(url::kHttpScheme) || gurl.SchemeIs(url::kHttpsScheme));
  1785. // "Promised requests MUST be cacheable and MUST be safe [...]" (RFC7540
  1786. // Section 8.2). Only cacheable safe request methods are GET and HEAD.
  1787. // GetPromisedUrlFromHeaders() guarantees that the method is GET or HEAD.
  1788. spdy::Http2HeaderBlock::const_iterator it =
  1789. headers.find(spdy::kHttp2MethodHeader);
  1790. DCHECK(it != headers.end() && (it->second == "GET" || it->second == "HEAD"));
  1791. // Verify we have a valid stream association.
  1792. auto associated_it = active_streams_.find(associated_stream_id);
  1793. if (associated_it == active_streams_.end()) {
  1794. RecordSpdyPushedStreamFateHistogram(
  1795. SpdyPushedStreamFate::kInactiveAssociatedStream);
  1796. EnqueueResetStreamFrame(stream_id, request_priority,
  1797. spdy::ERROR_CODE_STREAM_CLOSED,
  1798. "Inactive associated stream.");
  1799. return;
  1800. }
  1801. // Cross-origin push validation.
  1802. GURL associated_url(associated_it->second->url());
  1803. if (associated_url.DeprecatedGetOriginAsURL() !=
  1804. gurl.DeprecatedGetOriginAsURL()) {
  1805. if (!gurl.SchemeIs(url::kHttpsScheme)) {
  1806. RecordSpdyPushedStreamFateHistogram(
  1807. SpdyPushedStreamFate::kNonHttpsPushedScheme);
  1808. EnqueueResetStreamFrame(stream_id, request_priority,
  1809. spdy::ERROR_CODE_REFUSED_STREAM,
  1810. "Pushed URL must have https scheme.");
  1811. return;
  1812. }
  1813. if (!associated_url.SchemeIs(url::kHttpsScheme)) {
  1814. RecordSpdyPushedStreamFateHistogram(
  1815. SpdyPushedStreamFate::kNonHttpsAssociatedScheme);
  1816. EnqueueResetStreamFrame(stream_id, request_priority,
  1817. spdy::ERROR_CODE_REFUSED_STREAM,
  1818. "Associated URL must have https scheme.");
  1819. return;
  1820. }
  1821. SSLInfo ssl_info;
  1822. CHECK(GetSSLInfo(&ssl_info));
  1823. if (!CanPool(transport_security_state_, ssl_info, *ssl_config_service_,
  1824. associated_url.host(), gurl.host(),
  1825. spdy_session_key_.network_isolation_key())) {
  1826. RecordSpdyPushedStreamFateHistogram(
  1827. SpdyPushedStreamFate::kCertificateMismatch);
  1828. EnqueueResetStreamFrame(stream_id, request_priority,
  1829. spdy::ERROR_CODE_REFUSED_STREAM,
  1830. "Certificate does not match pushed URL.");
  1831. return;
  1832. }
  1833. }
  1834. // Insertion fails if there already is a pushed stream with the same path.
  1835. if (!pool_->push_promise_index()->RegisterUnclaimedPushedStream(
  1836. gurl, stream_id, this)) {
  1837. RecordSpdyPushedStreamFateHistogram(SpdyPushedStreamFate::kDuplicateUrl);
  1838. EnqueueResetStreamFrame(stream_id, request_priority,
  1839. spdy::ERROR_CODE_REFUSED_STREAM,
  1840. "Duplicate pushed stream with url: " + gurl.spec());
  1841. return;
  1842. }
  1843. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  1844. FROM_HERE,
  1845. base::BindOnce(&SpdySession::CancelPushedStreamIfUnclaimed, GetWeakPtr(),
  1846. stream_id),
  1847. base::Seconds(kPushedStreamLifetimeSeconds));
  1848. net::NetworkTrafficAnnotationTag traffic_annotation =
  1849. net::DefineNetworkTrafficAnnotation("spdy_push_stream", R"(
  1850. semantics {
  1851. sender: "Spdy Session"
  1852. description:
  1853. "When a web server needs to push a response to a client, an "
  1854. "incoming stream is created to reply the client with pushed "
  1855. "message instead of a message from the network."
  1856. trigger:
  1857. "A request by a server to push a response to the client."
  1858. data: "None."
  1859. destination: OTHER
  1860. destination_other:
  1861. "This stream is not used for sending data."
  1862. }
  1863. policy {
  1864. cookies_allowed: NO
  1865. setting: "This feature cannot be disabled."
  1866. policy_exception_justification: "Essential for navigation."
  1867. }
  1868. )");
  1869. auto stream = std::make_unique<SpdyStream>(
  1870. SPDY_PUSH_STREAM, GetWeakPtr(), gurl, request_priority,
  1871. stream_initial_send_window_size_, stream_max_recv_window_size_, net_log_,
  1872. traffic_annotation, false /* detect_broken_connection */);
  1873. stream->set_stream_id(stream_id);
  1874. // Convert RequestPriority to a spdy::SpdyPriority to send in a PRIORITY
  1875. // frame.
  1876. spdy::SpdyPriority spdy_priority =
  1877. ConvertRequestPriorityToSpdyPriority(request_priority);
  1878. spdy::SpdyStreamId dependency_id = 0;
  1879. int weight = 0;
  1880. bool exclusive = false;
  1881. priority_dependency_state_.OnStreamCreation(
  1882. stream_id, spdy_priority, &dependency_id, &weight, &exclusive);
  1883. EnqueuePriorityFrame(stream_id, dependency_id, weight, exclusive);
  1884. // PUSH_PROMISE arrives on associated stream.
  1885. associated_it->second->AddRawReceivedBytes(last_compressed_frame_len_);
  1886. last_compressed_frame_len_ = 0;
  1887. InsertActivatedStream(std::move(stream));
  1888. auto active_it = active_streams_.find(stream_id);
  1889. DCHECK(active_it != active_streams_.end());
  1890. // Notify the push_delegate that a push promise has been received.
  1891. if (push_delegate_) {
  1892. push_delegate_->OnPush(std::make_unique<SpdyServerPushHelper>(
  1893. weak_factory_.GetWeakPtr(), gurl),
  1894. net_log_);
  1895. }
  1896. active_it->second->OnPushPromiseHeadersReceived(std::move(headers),
  1897. std::move(gurl));
  1898. DCHECK(active_it->second->IsReservedRemote());
  1899. num_pushed_streams_++;
  1900. return;
  1901. }
  1902. void SpdySession::CloseActiveStreamIterator(ActiveStreamMap::iterator it,
  1903. int status) {
  1904. // TODO(mbelshe): We should send a RST_STREAM control frame here
  1905. // so that the server can cancel a large send.
  1906. std::unique_ptr<SpdyStream> owned_stream(it->second);
  1907. active_streams_.erase(it);
  1908. priority_dependency_state_.OnStreamDestruction(owned_stream->stream_id());
  1909. // TODO(akalin): When SpdyStream was ref-counted (and
  1910. // |unclaimed_pushed_streams_| held scoped_refptr<SpdyStream>), this
  1911. // was only done when status was not OK. This meant that pushed
  1912. // streams can still be claimed after they're closed. This is
  1913. // probably something that we still want to support, although server
  1914. // push is hardly used. Write tests for this and fix this. (See
  1915. // http://crbug.com/261712 .)
  1916. if (owned_stream->type() == SPDY_PUSH_STREAM) {
  1917. if (pool_->push_promise_index()->UnregisterUnclaimedPushedStream(
  1918. owned_stream->url(), owned_stream->stream_id(), this)) {
  1919. bytes_pushed_and_unclaimed_count_ += owned_stream->recv_bytes();
  1920. }
  1921. bytes_pushed_count_ += owned_stream->recv_bytes();
  1922. num_pushed_streams_--;
  1923. if (!owned_stream->IsReservedRemote())
  1924. num_active_pushed_streams_--;
  1925. }
  1926. DeleteStream(std::move(owned_stream), status);
  1927. // If the socket belongs to a socket pool, and there are no active streams,
  1928. // and the socket pool is stalled, then close the session to free up a socket
  1929. // slot.
  1930. if (client_socket_handle_ && active_streams_.empty() &&
  1931. created_streams_.empty() && client_socket_handle_->IsPoolStalled()) {
  1932. DoDrainSession(ERR_CONNECTION_CLOSED, "Closing idle connection.");
  1933. }
  1934. }
  1935. void SpdySession::CloseCreatedStreamIterator(CreatedStreamSet::iterator it,
  1936. int status) {
  1937. std::unique_ptr<SpdyStream> owned_stream(*it);
  1938. created_streams_.erase(it);
  1939. DeleteStream(std::move(owned_stream), status);
  1940. }
  1941. void SpdySession::ResetStreamIterator(ActiveStreamMap::iterator it,
  1942. int error,
  1943. const std::string& description) {
  1944. // Send the RST_STREAM frame first as CloseActiveStreamIterator()
  1945. // may close us.
  1946. spdy::SpdyErrorCode error_code = spdy::ERROR_CODE_PROTOCOL_ERROR;
  1947. if (error == ERR_FAILED) {
  1948. error_code = spdy::ERROR_CODE_INTERNAL_ERROR;
  1949. } else if (error == ERR_ABORTED ||
  1950. error == ERR_HTTP2_PUSHED_RESPONSE_DOES_NOT_MATCH) {
  1951. error_code = spdy::ERROR_CODE_CANCEL;
  1952. } else if (error == ERR_HTTP2_FLOW_CONTROL_ERROR) {
  1953. error_code = spdy::ERROR_CODE_FLOW_CONTROL_ERROR;
  1954. } else if (error == ERR_TIMED_OUT ||
  1955. error == ERR_HTTP2_CLIENT_REFUSED_STREAM) {
  1956. error_code = spdy::ERROR_CODE_REFUSED_STREAM;
  1957. } else if (error == ERR_HTTP2_STREAM_CLOSED) {
  1958. error_code = spdy::ERROR_CODE_STREAM_CLOSED;
  1959. }
  1960. spdy::SpdyStreamId stream_id = it->first;
  1961. RequestPriority priority = it->second->priority();
  1962. EnqueueResetStreamFrame(stream_id, priority, error_code, description);
  1963. // Removes any pending writes for the stream except for possibly an
  1964. // in-flight one.
  1965. CloseActiveStreamIterator(it, error);
  1966. }
  1967. void SpdySession::EnqueueResetStreamFrame(spdy::SpdyStreamId stream_id,
  1968. RequestPriority priority,
  1969. spdy::SpdyErrorCode error_code,
  1970. const std::string& description) {
  1971. DCHECK_NE(stream_id, 0u);
  1972. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_RST_STREAM, [&] {
  1973. return NetLogSpdySendRstStreamParams(stream_id, error_code, description);
  1974. });
  1975. DCHECK(buffered_spdy_framer_.get());
  1976. std::unique_ptr<spdy::SpdySerializedFrame> rst_frame(
  1977. buffered_spdy_framer_->CreateRstStream(stream_id, error_code));
  1978. EnqueueSessionWrite(priority, spdy::SpdyFrameType::RST_STREAM,
  1979. std::move(rst_frame));
  1980. RecordProtocolErrorHistogram(MapRstStreamStatusToProtocolError(error_code));
  1981. }
  1982. void SpdySession::EnqueuePriorityFrame(spdy::SpdyStreamId stream_id,
  1983. spdy::SpdyStreamId dependency_id,
  1984. int weight,
  1985. bool exclusive) {
  1986. net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_SEND_PRIORITY, [&] {
  1987. return NetLogSpdyPriorityParams(stream_id, dependency_id, weight,
  1988. exclusive);
  1989. });
  1990. DCHECK(buffered_spdy_framer_.get());
  1991. std::unique_ptr<spdy::SpdySerializedFrame> frame(
  1992. buffered_spdy_framer_->CreatePriority(stream_id, dependency_id, weight,
  1993. exclusive));
  1994. // PRIORITY frames describe sequenced updates to the tree, so they must
  1995. // be serialized. We do this by queueing all PRIORITY frames at HIGHEST
  1996. // priority.
  1997. EnqueueWrite(HIGHEST, spdy::SpdyFrameType::PRIORITY,
  1998. std::make_unique<SimpleBufferProducer>(
  1999. std::make_unique<SpdyBuffer>(std::move(frame))),
  2000. base::WeakPtr<SpdyStream>(),
  2001. kSpdySessionCommandsTrafficAnnotation);
  2002. }
  2003. void SpdySession::PumpReadLoop(ReadState expected_read_state, int result) {
  2004. CHECK(!in_io_loop_);
  2005. if (availability_state_ == STATE_DRAINING) {
  2006. return;
  2007. }
  2008. std::ignore = DoReadLoop(expected_read_state, result);
  2009. }
  2010. int SpdySession::DoReadLoop(ReadState expected_read_state, int result) {
  2011. CHECK(!in_io_loop_);
  2012. CHECK_EQ(read_state_, expected_read_state);
  2013. in_io_loop_ = true;
  2014. int bytes_read_without_yielding = 0;
  2015. const base::TimeTicks yield_after_time =
  2016. time_func_() + base::Milliseconds(kYieldAfterDurationMilliseconds);
  2017. // Loop until the session is draining, the read becomes blocked, or
  2018. // the read limit is exceeded.
  2019. while (true) {
  2020. switch (read_state_) {
  2021. case READ_STATE_DO_READ:
  2022. CHECK_EQ(result, OK);
  2023. result = DoRead();
  2024. break;
  2025. case READ_STATE_DO_READ_COMPLETE:
  2026. if (result > 0)
  2027. bytes_read_without_yielding += result;
  2028. result = DoReadComplete(result);
  2029. break;
  2030. default:
  2031. NOTREACHED() << "read_state_: " << read_state_;
  2032. break;
  2033. }
  2034. if (availability_state_ == STATE_DRAINING)
  2035. break;
  2036. if (result == ERR_IO_PENDING)
  2037. break;
  2038. if (read_state_ == READ_STATE_DO_READ &&
  2039. (bytes_read_without_yielding > kYieldAfterBytesRead ||
  2040. time_func_() > yield_after_time)) {
  2041. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2042. FROM_HERE,
  2043. base::BindOnce(&SpdySession::PumpReadLoop, weak_factory_.GetWeakPtr(),
  2044. READ_STATE_DO_READ, OK));
  2045. result = ERR_IO_PENDING;
  2046. break;
  2047. }
  2048. }
  2049. CHECK(in_io_loop_);
  2050. in_io_loop_ = false;
  2051. return result;
  2052. }
  2053. int SpdySession::DoRead() {
  2054. DCHECK(!read_buffer_);
  2055. CHECK(in_io_loop_);
  2056. CHECK(socket_);
  2057. read_state_ = READ_STATE_DO_READ_COMPLETE;
  2058. read_buffer_ = base::MakeRefCounted<IOBuffer>(kReadBufferSize);
  2059. int rv = socket_->ReadIfReady(
  2060. read_buffer_.get(), kReadBufferSize,
  2061. base::BindOnce(&SpdySession::PumpReadLoop, weak_factory_.GetWeakPtr(),
  2062. READ_STATE_DO_READ));
  2063. if (rv == ERR_IO_PENDING) {
  2064. read_buffer_ = nullptr;
  2065. read_state_ = READ_STATE_DO_READ;
  2066. return rv;
  2067. }
  2068. if (rv == ERR_READ_IF_READY_NOT_IMPLEMENTED) {
  2069. // Fallback to regular Read().
  2070. return socket_->Read(
  2071. read_buffer_.get(), kReadBufferSize,
  2072. base::BindOnce(&SpdySession::PumpReadLoop, weak_factory_.GetWeakPtr(),
  2073. READ_STATE_DO_READ_COMPLETE));
  2074. }
  2075. return rv;
  2076. }
  2077. int SpdySession::DoReadComplete(int result) {
  2078. DCHECK(read_buffer_);
  2079. CHECK(in_io_loop_);
  2080. // Parse a frame. For now this code requires that the frame fit into our
  2081. // buffer (kReadBufferSize).
  2082. // TODO(mbelshe): support arbitrarily large frames!
  2083. if (result == 0) {
  2084. DoDrainSession(ERR_CONNECTION_CLOSED, "Connection closed");
  2085. return ERR_CONNECTION_CLOSED;
  2086. }
  2087. if (result < 0) {
  2088. DoDrainSession(
  2089. static_cast<Error>(result),
  2090. base::StringPrintf("Error %d reading from socket.", -result));
  2091. return result;
  2092. }
  2093. CHECK_LE(result, kReadBufferSize);
  2094. last_read_time_ = time_func_();
  2095. DCHECK(buffered_spdy_framer_.get());
  2096. char* data = read_buffer_->data();
  2097. while (result > 0) {
  2098. uint32_t bytes_processed =
  2099. buffered_spdy_framer_->ProcessInput(data, result);
  2100. result -= bytes_processed;
  2101. data += bytes_processed;
  2102. if (availability_state_ == STATE_DRAINING) {
  2103. return ERR_CONNECTION_CLOSED;
  2104. }
  2105. DCHECK_EQ(buffered_spdy_framer_->spdy_framer_error(),
  2106. http2::Http2DecoderAdapter::SPDY_NO_ERROR);
  2107. }
  2108. read_buffer_ = nullptr;
  2109. read_state_ = READ_STATE_DO_READ;
  2110. return OK;
  2111. }
  2112. void SpdySession::PumpWriteLoop(WriteState expected_write_state, int result) {
  2113. CHECK(!in_io_loop_);
  2114. DCHECK_EQ(write_state_, expected_write_state);
  2115. DoWriteLoop(expected_write_state, result);
  2116. if (availability_state_ == STATE_DRAINING && !in_flight_write_ &&
  2117. write_queue_.IsEmpty()) {
  2118. pool_->RemoveUnavailableSession(GetWeakPtr()); // Destroys |this|.
  2119. return;
  2120. }
  2121. }
  2122. void SpdySession::MaybePostWriteLoop() {
  2123. if (write_state_ == WRITE_STATE_IDLE) {
  2124. CHECK(!in_flight_write_);
  2125. write_state_ = WRITE_STATE_DO_WRITE;
  2126. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2127. FROM_HERE,
  2128. base::BindOnce(&SpdySession::PumpWriteLoop, weak_factory_.GetWeakPtr(),
  2129. WRITE_STATE_DO_WRITE, OK));
  2130. }
  2131. }
  2132. int SpdySession::DoWriteLoop(WriteState expected_write_state, int result) {
  2133. CHECK(!in_io_loop_);
  2134. DCHECK_NE(write_state_, WRITE_STATE_IDLE);
  2135. DCHECK_EQ(write_state_, expected_write_state);
  2136. in_io_loop_ = true;
  2137. // Loop until the session is closed or the write becomes blocked.
  2138. while (true) {
  2139. switch (write_state_) {
  2140. case WRITE_STATE_DO_WRITE:
  2141. DCHECK_EQ(result, OK);
  2142. result = DoWrite();
  2143. break;
  2144. case WRITE_STATE_DO_WRITE_COMPLETE:
  2145. result = DoWriteComplete(result);
  2146. break;
  2147. case WRITE_STATE_IDLE:
  2148. default:
  2149. NOTREACHED() << "write_state_: " << write_state_;
  2150. break;
  2151. }
  2152. if (write_state_ == WRITE_STATE_IDLE) {
  2153. DCHECK_EQ(result, ERR_IO_PENDING);
  2154. break;
  2155. }
  2156. if (result == ERR_IO_PENDING)
  2157. break;
  2158. }
  2159. CHECK(in_io_loop_);
  2160. in_io_loop_ = false;
  2161. return result;
  2162. }
  2163. int SpdySession::DoWrite() {
  2164. CHECK(in_io_loop_);
  2165. DCHECK(buffered_spdy_framer_);
  2166. if (in_flight_write_) {
  2167. DCHECK_GT(in_flight_write_->GetRemainingSize(), 0u);
  2168. } else {
  2169. // Grab the next frame to send.
  2170. spdy::SpdyFrameType frame_type = spdy::SpdyFrameType::DATA;
  2171. std::unique_ptr<SpdyBufferProducer> producer;
  2172. base::WeakPtr<SpdyStream> stream;
  2173. if (!write_queue_.Dequeue(&frame_type, &producer, &stream,
  2174. &in_flight_write_traffic_annotation_)) {
  2175. write_state_ = WRITE_STATE_IDLE;
  2176. return ERR_IO_PENDING;
  2177. }
  2178. if (stream.get())
  2179. CHECK(!stream->IsClosed());
  2180. // Activate the stream only when sending the HEADERS frame to
  2181. // guarantee monotonically-increasing stream IDs.
  2182. if (frame_type == spdy::SpdyFrameType::HEADERS) {
  2183. CHECK(stream.get());
  2184. CHECK_EQ(stream->stream_id(), 0u);
  2185. std::unique_ptr<SpdyStream> owned_stream =
  2186. ActivateCreatedStream(stream.get());
  2187. InsertActivatedStream(std::move(owned_stream));
  2188. if (stream_hi_water_mark_ > kLastStreamId) {
  2189. CHECK_EQ(stream->stream_id(), kLastStreamId);
  2190. // We've exhausted the stream ID space, and no new streams may be
  2191. // created after this one.
  2192. MakeUnavailable();
  2193. StartGoingAway(kLastStreamId, ERR_HTTP2_PROTOCOL_ERROR);
  2194. }
  2195. }
  2196. in_flight_write_ = producer->ProduceBuffer();
  2197. if (!in_flight_write_) {
  2198. NOTREACHED();
  2199. return ERR_UNEXPECTED;
  2200. }
  2201. in_flight_write_frame_type_ = frame_type;
  2202. in_flight_write_frame_size_ = in_flight_write_->GetRemainingSize();
  2203. DCHECK_GE(in_flight_write_frame_size_, spdy::kFrameMinimumSize);
  2204. in_flight_write_stream_ = stream;
  2205. }
  2206. write_state_ = WRITE_STATE_DO_WRITE_COMPLETE;
  2207. scoped_refptr<IOBuffer> write_io_buffer =
  2208. in_flight_write_->GetIOBufferForRemainingData();
  2209. return socket_->Write(
  2210. write_io_buffer.get(), in_flight_write_->GetRemainingSize(),
  2211. base::BindOnce(&SpdySession::PumpWriteLoop, weak_factory_.GetWeakPtr(),
  2212. WRITE_STATE_DO_WRITE_COMPLETE),
  2213. NetworkTrafficAnnotationTag(in_flight_write_traffic_annotation_));
  2214. }
  2215. int SpdySession::DoWriteComplete(int result) {
  2216. CHECK(in_io_loop_);
  2217. DCHECK_NE(result, ERR_IO_PENDING);
  2218. DCHECK_GT(in_flight_write_->GetRemainingSize(), 0u);
  2219. if (result < 0) {
  2220. DCHECK_NE(result, ERR_IO_PENDING);
  2221. in_flight_write_.reset();
  2222. in_flight_write_frame_type_ = spdy::SpdyFrameType::DATA;
  2223. in_flight_write_frame_size_ = 0;
  2224. in_flight_write_stream_.reset();
  2225. in_flight_write_traffic_annotation_.reset();
  2226. write_state_ = WRITE_STATE_DO_WRITE;
  2227. DoDrainSession(static_cast<Error>(result), "Write error");
  2228. return OK;
  2229. }
  2230. // It should not be possible to have written more bytes than our
  2231. // in_flight_write_.
  2232. DCHECK_LE(static_cast<size_t>(result), in_flight_write_->GetRemainingSize());
  2233. if (result > 0) {
  2234. in_flight_write_->Consume(static_cast<size_t>(result));
  2235. if (in_flight_write_stream_.get())
  2236. in_flight_write_stream_->AddRawSentBytes(static_cast<size_t>(result));
  2237. // We only notify the stream when we've fully written the pending frame.
  2238. if (in_flight_write_->GetRemainingSize() == 0) {
  2239. // It is possible that the stream was cancelled while we were
  2240. // writing to the socket.
  2241. if (in_flight_write_stream_.get()) {
  2242. DCHECK_GT(in_flight_write_frame_size_, 0u);
  2243. in_flight_write_stream_->OnFrameWriteComplete(
  2244. in_flight_write_frame_type_, in_flight_write_frame_size_);
  2245. }
  2246. // Cleanup the write which just completed.
  2247. in_flight_write_.reset();
  2248. in_flight_write_frame_type_ = spdy::SpdyFrameType::DATA;
  2249. in_flight_write_frame_size_ = 0;
  2250. in_flight_write_stream_.reset();
  2251. }
  2252. }
  2253. write_state_ = WRITE_STATE_DO_WRITE;
  2254. return OK;
  2255. }
  2256. void SpdySession::NotifyRequestsOfConfirmation(int rv) {
  2257. for (auto& callback : waiting_for_confirmation_callbacks_) {
  2258. base::ThreadTaskRunnerHandle::Get()->PostTask(
  2259. FROM_HERE, base::BindOnce(std::move(callback), rv));
  2260. }
  2261. waiting_for_confirmation_callbacks_.clear();
  2262. in_confirm_handshake_ = false;
  2263. }
  2264. void SpdySession::SendInitialData() {
  2265. DCHECK(enable_sending_initial_data_);
  2266. DCHECK(buffered_spdy_framer_.get());
  2267. // Prepare initial SETTINGS frame. Only send settings that have a value
  2268. // different from the protocol default value.
  2269. spdy::SettingsMap settings_map;
  2270. for (auto setting : initial_settings_) {
  2271. if (!IsSpdySettingAtDefaultInitialValue(setting.first, setting.second)) {
  2272. settings_map.insert(setting);
  2273. }
  2274. }
  2275. if (enable_http2_settings_grease_) {
  2276. spdy::SpdySettingsId greased_id = 0x0a0a +
  2277. 0x1000 * base::RandGenerator(0xf + 1) +
  2278. 0x0010 * base::RandGenerator(0xf + 1);
  2279. uint32_t greased_value = base::RandGenerator(
  2280. static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) + 1);
  2281. // Let insertion silently fail if `settings_map` already contains
  2282. // `greased_id`.
  2283. settings_map.insert(std::make_pair(greased_id, greased_value));
  2284. }
  2285. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_SETTINGS, [&] {
  2286. return NetLogSpdySendSettingsParams(&settings_map);
  2287. });
  2288. std::unique_ptr<spdy::SpdySerializedFrame> settings_frame(
  2289. buffered_spdy_framer_->CreateSettings(settings_map));
  2290. // Prepare initial WINDOW_UPDATE frame.
  2291. // Make sure |session_max_recv_window_size_ - session_recv_window_size_|
  2292. // does not underflow.
  2293. DCHECK_GE(session_max_recv_window_size_, session_recv_window_size_);
  2294. DCHECK_GE(session_recv_window_size_, 0);
  2295. DCHECK_EQ(0, session_unacked_recv_window_bytes_);
  2296. std::unique_ptr<spdy::SpdySerializedFrame> window_update_frame;
  2297. const bool send_window_update =
  2298. session_max_recv_window_size_ > session_recv_window_size_;
  2299. if (send_window_update) {
  2300. const int32_t delta_window_size =
  2301. session_max_recv_window_size_ - session_recv_window_size_;
  2302. session_recv_window_size_ += delta_window_size;
  2303. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_UPDATE_RECV_WINDOW, [&] {
  2304. return NetLogSpdySessionWindowUpdateParams(delta_window_size,
  2305. session_recv_window_size_);
  2306. });
  2307. last_recv_window_update_ = base::TimeTicks::Now();
  2308. session_unacked_recv_window_bytes_ += delta_window_size;
  2309. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_WINDOW_UPDATE, [&] {
  2310. return NetLogSpdyWindowUpdateFrameParams(
  2311. spdy::kSessionFlowControlStreamId,
  2312. session_unacked_recv_window_bytes_);
  2313. });
  2314. window_update_frame = buffered_spdy_framer_->CreateWindowUpdate(
  2315. spdy::kSessionFlowControlStreamId, session_unacked_recv_window_bytes_);
  2316. session_unacked_recv_window_bytes_ = 0;
  2317. }
  2318. // Create a single frame to hold connection prefix, initial SETTINGS frame,
  2319. // and optional initial WINDOW_UPDATE frame, so that they are sent on the wire
  2320. // in a single packet.
  2321. size_t initial_frame_size =
  2322. spdy::kHttp2ConnectionHeaderPrefixSize + settings_frame->size();
  2323. if (send_window_update)
  2324. initial_frame_size += window_update_frame->size();
  2325. auto initial_frame_data = std::make_unique<char[]>(initial_frame_size);
  2326. size_t offset = 0;
  2327. memcpy(initial_frame_data.get() + offset, spdy::kHttp2ConnectionHeaderPrefix,
  2328. spdy::kHttp2ConnectionHeaderPrefixSize);
  2329. offset += spdy::kHttp2ConnectionHeaderPrefixSize;
  2330. memcpy(initial_frame_data.get() + offset, settings_frame->data(),
  2331. settings_frame->size());
  2332. offset += settings_frame->size();
  2333. if (send_window_update) {
  2334. memcpy(initial_frame_data.get() + offset, window_update_frame->data(),
  2335. window_update_frame->size());
  2336. }
  2337. auto initial_frame = std::make_unique<spdy::SpdySerializedFrame>(
  2338. initial_frame_data.release(), initial_frame_size,
  2339. /* owns_buffer = */ true);
  2340. EnqueueSessionWrite(HIGHEST, spdy::SpdyFrameType::SETTINGS,
  2341. std::move(initial_frame));
  2342. }
  2343. void SpdySession::HandleSetting(uint32_t id, uint32_t value) {
  2344. switch (id) {
  2345. case spdy::SETTINGS_HEADER_TABLE_SIZE:
  2346. buffered_spdy_framer_->UpdateHeaderEncoderTableSize(value);
  2347. break;
  2348. case spdy::SETTINGS_MAX_CONCURRENT_STREAMS:
  2349. max_concurrent_streams_ =
  2350. std::min(static_cast<size_t>(value), kMaxConcurrentStreamLimit);
  2351. ProcessPendingStreamRequests();
  2352. break;
  2353. case spdy::SETTINGS_INITIAL_WINDOW_SIZE: {
  2354. if (value > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
  2355. net_log_.AddEventWithIntParams(
  2356. NetLogEventType::HTTP2_SESSION_INITIAL_WINDOW_SIZE_OUT_OF_RANGE,
  2357. "initial_window_size", value);
  2358. return;
  2359. }
  2360. // spdy::SETTINGS_INITIAL_WINDOW_SIZE updates initial_send_window_size_
  2361. // only.
  2362. int32_t delta_window_size =
  2363. static_cast<int32_t>(value) - stream_initial_send_window_size_;
  2364. stream_initial_send_window_size_ = static_cast<int32_t>(value);
  2365. UpdateStreamsSendWindowSize(delta_window_size);
  2366. net_log_.AddEventWithIntParams(
  2367. NetLogEventType::HTTP2_SESSION_UPDATE_STREAMS_SEND_WINDOW_SIZE,
  2368. "delta_window_size", delta_window_size);
  2369. break;
  2370. }
  2371. case spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL:
  2372. if ((value != 0 && value != 1) || (support_websocket_ && value == 0)) {
  2373. DoDrainSession(
  2374. ERR_HTTP2_PROTOCOL_ERROR,
  2375. "Invalid value for spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL.");
  2376. return;
  2377. }
  2378. if (value == 1) {
  2379. support_websocket_ = true;
  2380. }
  2381. break;
  2382. case spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES:
  2383. if (value != 0 && value != 1) {
  2384. DoDrainSession(
  2385. ERR_HTTP2_PROTOCOL_ERROR,
  2386. "Invalid value for spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES.");
  2387. return;
  2388. }
  2389. if (settings_frame_received_) {
  2390. if (value != (deprecate_http2_priorities_ ? 1 : 0)) {
  2391. DoDrainSession(ERR_HTTP2_PROTOCOL_ERROR,
  2392. "spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES value "
  2393. "changed after first SETTINGS frame.");
  2394. return;
  2395. }
  2396. } else {
  2397. if (value == 1) {
  2398. deprecate_http2_priorities_ = true;
  2399. }
  2400. }
  2401. break;
  2402. }
  2403. }
  2404. void SpdySession::UpdateStreamsSendWindowSize(int32_t delta_window_size) {
  2405. for (const auto& value : active_streams_) {
  2406. if (!value.second->AdjustSendWindowSize(delta_window_size)) {
  2407. DoDrainSession(
  2408. ERR_HTTP2_FLOW_CONTROL_ERROR,
  2409. base::StringPrintf(
  2410. "New spdy::SETTINGS_INITIAL_WINDOW_SIZE value overflows "
  2411. "flow control window of stream %d.",
  2412. value.second->stream_id()));
  2413. return;
  2414. }
  2415. }
  2416. for (auto* const stream : created_streams_) {
  2417. if (!stream->AdjustSendWindowSize(delta_window_size)) {
  2418. DoDrainSession(
  2419. ERR_HTTP2_FLOW_CONTROL_ERROR,
  2420. base::StringPrintf(
  2421. "New spdy::SETTINGS_INITIAL_WINDOW_SIZE value overflows "
  2422. "flow control window of stream %d.",
  2423. stream->stream_id()));
  2424. return;
  2425. }
  2426. }
  2427. }
  2428. void SpdySession::MaybeCheckConnectionStatus() {
  2429. if (NetworkChangeNotifier::IsDefaultNetworkActive())
  2430. CheckConnectionStatus();
  2431. else
  2432. check_connection_on_radio_wakeup_ = true;
  2433. }
  2434. void SpdySession::MaybeSendPrefacePing() {
  2435. if (ping_in_flight_ || check_ping_status_pending_ ||
  2436. !enable_ping_based_connection_checking_) {
  2437. return;
  2438. }
  2439. // If there has been no read activity in the session for some time,
  2440. // then send a preface-PING.
  2441. if (time_func_() > last_read_time_ + connection_at_risk_of_loss_time_)
  2442. WritePingFrame(next_ping_id_, false);
  2443. }
  2444. void SpdySession::SendWindowUpdateFrame(spdy::SpdyStreamId stream_id,
  2445. uint32_t delta_window_size,
  2446. RequestPriority priority) {
  2447. ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
  2448. if (it != active_streams_.end()) {
  2449. CHECK_EQ(it->second->stream_id(), stream_id);
  2450. } else {
  2451. CHECK_EQ(stream_id, spdy::kSessionFlowControlStreamId);
  2452. }
  2453. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_WINDOW_UPDATE, [&] {
  2454. return NetLogSpdyWindowUpdateFrameParams(stream_id, delta_window_size);
  2455. });
  2456. DCHECK(buffered_spdy_framer_.get());
  2457. std::unique_ptr<spdy::SpdySerializedFrame> window_update_frame(
  2458. buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size));
  2459. EnqueueSessionWrite(priority, spdy::SpdyFrameType::WINDOW_UPDATE,
  2460. std::move(window_update_frame));
  2461. }
  2462. void SpdySession::WritePingFrame(spdy::SpdyPingId unique_id, bool is_ack) {
  2463. DCHECK(buffered_spdy_framer_.get());
  2464. std::unique_ptr<spdy::SpdySerializedFrame> ping_frame(
  2465. buffered_spdy_framer_->CreatePingFrame(unique_id, is_ack));
  2466. EnqueueSessionWrite(HIGHEST, spdy::SpdyFrameType::PING,
  2467. std::move(ping_frame));
  2468. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_PING, [&] {
  2469. return NetLogSpdyPingParams(unique_id, is_ack, "sent");
  2470. });
  2471. if (!is_ack) {
  2472. DCHECK(!ping_in_flight_);
  2473. ping_in_flight_ = true;
  2474. ++next_ping_id_;
  2475. PlanToCheckPingStatus();
  2476. last_ping_sent_time_ = time_func_();
  2477. }
  2478. }
  2479. void SpdySession::PlanToCheckPingStatus() {
  2480. if (check_ping_status_pending_)
  2481. return;
  2482. check_ping_status_pending_ = true;
  2483. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  2484. FROM_HERE,
  2485. base::BindOnce(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(),
  2486. time_func_()),
  2487. hung_interval_);
  2488. }
  2489. void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) {
  2490. CHECK(!in_io_loop_);
  2491. DCHECK(check_ping_status_pending_);
  2492. if (!ping_in_flight_) {
  2493. // A response has been received for the ping we had sent.
  2494. check_ping_status_pending_ = false;
  2495. return;
  2496. }
  2497. const base::TimeTicks now = time_func_();
  2498. if (now > last_read_time_ + hung_interval_ ||
  2499. last_read_time_ < last_check_time) {
  2500. check_ping_status_pending_ = false;
  2501. DoDrainSession(ERR_HTTP2_PING_FAILED, "Failed ping.");
  2502. return;
  2503. }
  2504. // Check the status of connection after a delay.
  2505. const base::TimeDelta delay = last_read_time_ + hung_interval_ - now;
  2506. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  2507. FROM_HERE,
  2508. base::BindOnce(&SpdySession::CheckPingStatus, weak_factory_.GetWeakPtr(),
  2509. now),
  2510. delay);
  2511. }
  2512. spdy::SpdyStreamId SpdySession::GetNewStreamId() {
  2513. CHECK_LE(stream_hi_water_mark_, kLastStreamId);
  2514. spdy::SpdyStreamId id = stream_hi_water_mark_;
  2515. stream_hi_water_mark_ += 2;
  2516. return id;
  2517. }
  2518. void SpdySession::EnqueueSessionWrite(
  2519. RequestPriority priority,
  2520. spdy::SpdyFrameType frame_type,
  2521. std::unique_ptr<spdy::SpdySerializedFrame> frame) {
  2522. DCHECK(frame_type == spdy::SpdyFrameType::RST_STREAM ||
  2523. frame_type == spdy::SpdyFrameType::SETTINGS ||
  2524. frame_type == spdy::SpdyFrameType::WINDOW_UPDATE ||
  2525. frame_type == spdy::SpdyFrameType::PING ||
  2526. frame_type == spdy::SpdyFrameType::GOAWAY);
  2527. DCHECK(IsSpdyFrameTypeWriteCapped(frame_type));
  2528. if (write_queue_.num_queued_capped_frames() >
  2529. session_max_queued_capped_frames_) {
  2530. LOG(WARNING)
  2531. << "Draining session due to exceeding max queued capped frames";
  2532. // Use ERR_CONNECTION_CLOSED to avoid sending a GOAWAY frame since that
  2533. // frame would also exceed the cap.
  2534. DoDrainSession(ERR_CONNECTION_CLOSED, "Exceeded max queued capped frames");
  2535. return;
  2536. }
  2537. auto buffer = std::make_unique<SpdyBuffer>(std::move(frame));
  2538. EnqueueWrite(priority, frame_type,
  2539. std::make_unique<SimpleBufferProducer>(std::move(buffer)),
  2540. base::WeakPtr<SpdyStream>(),
  2541. kSpdySessionCommandsTrafficAnnotation);
  2542. if (greased_http2_frame_ && frame_type == spdy::SpdyFrameType::SETTINGS) {
  2543. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_GREASED_FRAME, [&] {
  2544. return NetLogSpdyGreasedFrameParams(
  2545. /* stream_id = */ 0, greased_http2_frame_.value().type,
  2546. greased_http2_frame_.value().flags,
  2547. greased_http2_frame_.value().payload.length(), priority);
  2548. });
  2549. EnqueueWrite(
  2550. priority,
  2551. static_cast<spdy::SpdyFrameType>(greased_http2_frame_.value().type),
  2552. std::make_unique<GreasedBufferProducer>(base::WeakPtr<SpdyStream>(),
  2553. &greased_http2_frame_.value(),
  2554. buffered_spdy_framer_.get()),
  2555. base::WeakPtr<SpdyStream>(), kSpdySessionCommandsTrafficAnnotation);
  2556. }
  2557. }
  2558. void SpdySession::EnqueueWrite(
  2559. RequestPriority priority,
  2560. spdy::SpdyFrameType frame_type,
  2561. std::unique_ptr<SpdyBufferProducer> producer,
  2562. const base::WeakPtr<SpdyStream>& stream,
  2563. const NetworkTrafficAnnotationTag& traffic_annotation) {
  2564. if (availability_state_ == STATE_DRAINING)
  2565. return;
  2566. write_queue_.Enqueue(priority, frame_type, std::move(producer), stream,
  2567. traffic_annotation);
  2568. MaybePostWriteLoop();
  2569. }
  2570. void SpdySession::InsertCreatedStream(std::unique_ptr<SpdyStream> stream) {
  2571. CHECK_EQ(stream->stream_id(), 0u);
  2572. auto it = created_streams_.lower_bound(stream.get());
  2573. CHECK(it == created_streams_.end() || *it != stream.get());
  2574. created_streams_.insert(it, stream.release());
  2575. }
  2576. std::unique_ptr<SpdyStream> SpdySession::ActivateCreatedStream(
  2577. SpdyStream* stream) {
  2578. CHECK_EQ(stream->stream_id(), 0u);
  2579. auto it = created_streams_.find(stream);
  2580. CHECK(it != created_streams_.end());
  2581. stream->set_stream_id(GetNewStreamId());
  2582. std::unique_ptr<SpdyStream> owned_stream(stream);
  2583. created_streams_.erase(it);
  2584. return owned_stream;
  2585. }
  2586. void SpdySession::InsertActivatedStream(std::unique_ptr<SpdyStream> stream) {
  2587. spdy::SpdyStreamId stream_id = stream->stream_id();
  2588. CHECK_NE(stream_id, 0u);
  2589. std::pair<ActiveStreamMap::iterator, bool> result =
  2590. active_streams_.insert(std::make_pair(stream_id, stream.get()));
  2591. CHECK(result.second);
  2592. std::ignore = stream.release();
  2593. }
  2594. void SpdySession::DeleteStream(std::unique_ptr<SpdyStream> stream, int status) {
  2595. if (in_flight_write_stream_.get() == stream.get()) {
  2596. // If we're deleting the stream for the in-flight write, we still
  2597. // need to let the write complete, so we clear
  2598. // |in_flight_write_stream_| and let the write finish on its own
  2599. // without notifying |in_flight_write_stream_|.
  2600. in_flight_write_stream_.reset();
  2601. }
  2602. write_queue_.RemovePendingWritesForStream(stream.get());
  2603. if (stream->detect_broken_connection())
  2604. MaybeDisableBrokenConnectionDetection();
  2605. stream->OnClose(status);
  2606. if (availability_state_ == STATE_AVAILABLE) {
  2607. ProcessPendingStreamRequests();
  2608. }
  2609. }
  2610. void SpdySession::RecordHistograms() {
  2611. UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPerSession",
  2612. streams_initiated_count_, 1, 300, 50);
  2613. UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedPerSession",
  2614. streams_pushed_count_, 1, 300, 50);
  2615. UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsPushedAndClaimedPerSession",
  2616. streams_pushed_and_claimed_count_, 1, 300, 50);
  2617. UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyStreamsAbandonedPerSession",
  2618. streams_abandoned_count_, 1, 300, 50);
  2619. UMA_HISTOGRAM_COUNTS_1M("Net.SpdySession.PushedBytes", bytes_pushed_count_);
  2620. DCHECK_LE(bytes_pushed_and_unclaimed_count_, bytes_pushed_count_);
  2621. UMA_HISTOGRAM_COUNTS_1M("Net.SpdySession.PushedAndUnclaimedBytes",
  2622. bytes_pushed_and_unclaimed_count_);
  2623. UMA_HISTOGRAM_BOOLEAN("Net.SpdySession.ServerSupportsWebSocket",
  2624. support_websocket_);
  2625. }
  2626. void SpdySession::RecordProtocolErrorHistogram(
  2627. SpdyProtocolErrorDetails details) {
  2628. UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails2", details,
  2629. NUM_SPDY_PROTOCOL_ERROR_DETAILS);
  2630. if (base::EndsWith(host_port_pair().host(), "google.com",
  2631. base::CompareCase::INSENSITIVE_ASCII)) {
  2632. UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionErrorDetails_Google2", details,
  2633. NUM_SPDY_PROTOCOL_ERROR_DETAILS);
  2634. }
  2635. }
  2636. // static
  2637. void SpdySession::RecordPushedStreamVaryResponseHeaderHistogram(
  2638. const spdy::Http2HeaderBlock& headers) {
  2639. UMA_HISTOGRAM_ENUMERATION("Net.PushedStreamVaryResponseHeader",
  2640. ParseVaryInPushedResponse(headers),
  2641. kNumberOfVaryEntries);
  2642. }
  2643. void SpdySession::DcheckGoingAway() const {
  2644. #if DCHECK_IS_ON()
  2645. DCHECK_GE(availability_state_, STATE_GOING_AWAY);
  2646. for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
  2647. DCHECK(pending_create_stream_queues_[i].empty());
  2648. }
  2649. DCHECK(created_streams_.empty());
  2650. #endif
  2651. }
  2652. void SpdySession::DcheckDraining() const {
  2653. DcheckGoingAway();
  2654. DCHECK_EQ(availability_state_, STATE_DRAINING);
  2655. DCHECK(active_streams_.empty());
  2656. DCHECK_EQ(0u, pool_->push_promise_index()->CountStreamsForSession(this));
  2657. }
  2658. void SpdySession::DoDrainSession(Error err, const std::string& description) {
  2659. if (availability_state_ == STATE_DRAINING) {
  2660. return;
  2661. }
  2662. MakeUnavailable();
  2663. // Mark host_port_pair requiring HTTP/1.1 for subsequent connections.
  2664. if (err == ERR_HTTP_1_1_REQUIRED) {
  2665. http_server_properties_->SetHTTP11Required(
  2666. url::SchemeHostPort(url::kHttpsScheme, host_port_pair().host(),
  2667. host_port_pair().port()),
  2668. spdy_session_key_.network_isolation_key());
  2669. }
  2670. // If |err| indicates an error occurred, inform the peer that we're closing
  2671. // and why. Don't GOAWAY on a graceful or idle close, as that may
  2672. // unnecessarily wake the radio. We could technically GOAWAY on network errors
  2673. // (we'll probably fail to actually write it, but that's okay), however many
  2674. // unit-tests would need to be updated.
  2675. if (err != OK &&
  2676. err != ERR_ABORTED && // Used by SpdySessionPool to close idle sessions.
  2677. err != ERR_NETWORK_CHANGED && // Used to deprecate sessions on IP change.
  2678. err != ERR_SOCKET_NOT_CONNECTED && err != ERR_HTTP_1_1_REQUIRED &&
  2679. err != ERR_CONNECTION_CLOSED && err != ERR_CONNECTION_RESET) {
  2680. // Enqueue a GOAWAY to inform the peer of why we're closing the connection.
  2681. spdy::SpdyGoAwayIR goaway_ir(last_accepted_push_stream_id_,
  2682. MapNetErrorToGoAwayStatus(err), description);
  2683. auto frame = std::make_unique<spdy::SpdySerializedFrame>(
  2684. buffered_spdy_framer_->SerializeFrame(goaway_ir));
  2685. EnqueueSessionWrite(HIGHEST, spdy::SpdyFrameType::GOAWAY, std::move(frame));
  2686. }
  2687. availability_state_ = STATE_DRAINING;
  2688. error_on_close_ = err;
  2689. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_CLOSE, [&] {
  2690. return NetLogSpdySessionCloseParams(err, description);
  2691. });
  2692. base::UmaHistogramSparse("Net.SpdySession.ClosedOnError", -err);
  2693. if (err == OK) {
  2694. // We ought to be going away already, as this is a graceful close.
  2695. DcheckGoingAway();
  2696. } else {
  2697. StartGoingAway(0, err);
  2698. }
  2699. DcheckDraining();
  2700. MaybePostWriteLoop();
  2701. }
  2702. void SpdySession::LogAbandonedStream(SpdyStream* stream, Error status) {
  2703. DCHECK(stream);
  2704. stream->LogStreamError(status, "Abandoned.");
  2705. // We don't increment the streams abandoned counter here. If the
  2706. // stream isn't active (i.e., it hasn't written anything to the wire
  2707. // yet) then it's as if it never existed. If it is active, then
  2708. // LogAbandonedActiveStream() will increment the counters.
  2709. }
  2710. void SpdySession::LogAbandonedActiveStream(ActiveStreamMap::const_iterator it,
  2711. Error status) {
  2712. DCHECK_GT(it->first, 0u);
  2713. LogAbandonedStream(it->second, status);
  2714. ++streams_abandoned_count_;
  2715. }
  2716. void SpdySession::CompleteStreamRequest(
  2717. const base::WeakPtr<SpdyStreamRequest>& pending_request) {
  2718. // Abort if the request has already been cancelled.
  2719. if (!pending_request)
  2720. return;
  2721. base::WeakPtr<SpdyStream> stream;
  2722. int rv = TryCreateStream(pending_request, &stream);
  2723. if (rv == OK) {
  2724. DCHECK(stream);
  2725. pending_request->OnRequestCompleteSuccess(stream);
  2726. return;
  2727. }
  2728. DCHECK(!stream);
  2729. if (rv != ERR_IO_PENDING) {
  2730. pending_request->OnRequestCompleteFailure(rv);
  2731. }
  2732. }
  2733. void SpdySession::CancelPushedStreamIfUnclaimed(spdy::SpdyStreamId stream_id) {
  2734. auto active_it = active_streams_.find(stream_id);
  2735. if (active_it == active_streams_.end())
  2736. return;
  2737. // Make sure to cancel the correct stream. It is possible that the pushed
  2738. // stream |stream_id| is already claimed, and another stream has been pushed
  2739. // for the same URL.
  2740. const GURL& url = active_it->second->url();
  2741. if (pool_->push_promise_index()->FindStream(url, this) != stream_id) {
  2742. return;
  2743. }
  2744. RecordSpdyPushedStreamFateHistogram(SpdyPushedStreamFate::kTimeout);
  2745. LogAbandonedActiveStream(active_it, ERR_TIMED_OUT);
  2746. // CloseActiveStreamIterator() will remove the stream from
  2747. // |pool_->push_promise_index()|.
  2748. ResetStreamIterator(active_it, ERR_TIMED_OUT, "Stream not claimed.");
  2749. }
  2750. void SpdySession::OnError(
  2751. http2::Http2DecoderAdapter::SpdyFramerError spdy_framer_error) {
  2752. CHECK(in_io_loop_);
  2753. RecordProtocolErrorHistogram(
  2754. MapFramerErrorToProtocolError(spdy_framer_error));
  2755. std::string description = base::StringPrintf(
  2756. "Framer error: %d (%s).", spdy_framer_error,
  2757. http2::Http2DecoderAdapter::SpdyFramerErrorToString(spdy_framer_error));
  2758. DoDrainSession(MapFramerErrorToNetError(spdy_framer_error), description);
  2759. }
  2760. void SpdySession::OnStreamError(spdy::SpdyStreamId stream_id,
  2761. const std::string& description) {
  2762. CHECK(in_io_loop_);
  2763. auto it = active_streams_.find(stream_id);
  2764. if (it == active_streams_.end()) {
  2765. // We still want to send a frame to reset the stream even if we
  2766. // don't know anything about it.
  2767. EnqueueResetStreamFrame(stream_id, IDLE, spdy::ERROR_CODE_PROTOCOL_ERROR,
  2768. description);
  2769. return;
  2770. }
  2771. ResetStreamIterator(it, ERR_HTTP2_PROTOCOL_ERROR, description);
  2772. }
  2773. void SpdySession::OnPing(spdy::SpdyPingId unique_id, bool is_ack) {
  2774. CHECK(in_io_loop_);
  2775. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_PING, [&] {
  2776. return NetLogSpdyPingParams(unique_id, is_ack, "received");
  2777. });
  2778. // Send response to a PING from server.
  2779. if (!is_ack) {
  2780. WritePingFrame(unique_id, true);
  2781. return;
  2782. }
  2783. if (!ping_in_flight_) {
  2784. RecordProtocolErrorHistogram(PROTOCOL_ERROR_UNEXPECTED_PING);
  2785. DoDrainSession(ERR_HTTP2_PROTOCOL_ERROR, "Unexpected PING ACK.");
  2786. return;
  2787. }
  2788. ping_in_flight_ = false;
  2789. // Record RTT in histogram when there are no more pings in flight.
  2790. base::TimeDelta ping_duration = time_func_() - last_ping_sent_time_;
  2791. if (network_quality_estimator_) {
  2792. network_quality_estimator_->RecordSpdyPingLatency(host_port_pair(),
  2793. ping_duration);
  2794. }
  2795. }
  2796. void SpdySession::OnRstStream(spdy::SpdyStreamId stream_id,
  2797. spdy::SpdyErrorCode error_code) {
  2798. CHECK(in_io_loop_);
  2799. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_RST_STREAM, [&] {
  2800. return NetLogSpdyRecvRstStreamParams(stream_id, error_code);
  2801. });
  2802. auto it = active_streams_.find(stream_id);
  2803. if (it == active_streams_.end()) {
  2804. // NOTE: it may just be that the stream was cancelled.
  2805. LOG(WARNING) << "Received RST for invalid stream" << stream_id;
  2806. return;
  2807. }
  2808. DCHECK(it->second);
  2809. CHECK_EQ(it->second->stream_id(), stream_id);
  2810. if (it->second->ShouldRetryRSTPushStream()) {
  2811. CloseActiveStreamIterator(it,
  2812. ERR_HTTP2_CLAIMED_PUSHED_STREAM_RESET_BY_SERVER);
  2813. } else if (error_code == spdy::ERROR_CODE_NO_ERROR) {
  2814. CloseActiveStreamIterator(it, ERR_HTTP2_RST_STREAM_NO_ERROR_RECEIVED);
  2815. } else if (error_code == spdy::ERROR_CODE_REFUSED_STREAM) {
  2816. CloseActiveStreamIterator(it, ERR_HTTP2_SERVER_REFUSED_STREAM);
  2817. } else if (error_code == spdy::ERROR_CODE_HTTP_1_1_REQUIRED) {
  2818. // TODO(bnc): Record histogram with number of open streams capped at 50.
  2819. it->second->LogStreamError(ERR_HTTP_1_1_REQUIRED,
  2820. "Closing session because server reset stream "
  2821. "with ERR_HTTP_1_1_REQUIRED.");
  2822. DoDrainSession(ERR_HTTP_1_1_REQUIRED, "HTTP_1_1_REQUIRED for stream.");
  2823. } else {
  2824. RecordProtocolErrorHistogram(
  2825. PROTOCOL_ERROR_RST_STREAM_FOR_NON_ACTIVE_STREAM);
  2826. it->second->LogStreamError(ERR_HTTP2_PROTOCOL_ERROR,
  2827. "Server reset stream.");
  2828. // TODO(mbelshe): Map from Spdy-protocol errors to something sensical.
  2829. // For now, it doesn't matter much - it is a protocol error.
  2830. CloseActiveStreamIterator(it, ERR_HTTP2_PROTOCOL_ERROR);
  2831. }
  2832. }
  2833. void SpdySession::OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
  2834. spdy::SpdyErrorCode error_code,
  2835. base::StringPiece debug_data) {
  2836. CHECK(in_io_loop_);
  2837. // Use sparse histogram to record the unlikely case that a server sends
  2838. // an unknown error code.
  2839. base::UmaHistogramSparse("Net.SpdySession.GoAwayReceived", error_code);
  2840. net_log_.AddEvent(
  2841. NetLogEventType::HTTP2_SESSION_RECV_GOAWAY,
  2842. [&](NetLogCaptureMode capture_mode) {
  2843. return NetLogSpdyRecvGoAwayParams(
  2844. last_accepted_stream_id, active_streams_.size(),
  2845. pool_->push_promise_index()->CountStreamsForSession(this),
  2846. error_code, debug_data, capture_mode);
  2847. });
  2848. MakeUnavailable();
  2849. if (error_code == spdy::ERROR_CODE_HTTP_1_1_REQUIRED) {
  2850. // TODO(bnc): Record histogram with number of open streams capped at 50.
  2851. DoDrainSession(ERR_HTTP_1_1_REQUIRED, "HTTP_1_1_REQUIRED for stream.");
  2852. } else if (error_code == spdy::ERROR_CODE_NO_ERROR) {
  2853. StartGoingAway(last_accepted_stream_id, ERR_HTTP2_SERVER_REFUSED_STREAM);
  2854. } else {
  2855. StartGoingAway(last_accepted_stream_id, ERR_HTTP2_PROTOCOL_ERROR);
  2856. }
  2857. // This is to handle the case when we already don't have any active
  2858. // streams (i.e., StartGoingAway() did nothing). Otherwise, we have
  2859. // active streams and so the last one being closed will finish the
  2860. // going away process (see DeleteStream()).
  2861. MaybeFinishGoingAway();
  2862. }
  2863. void SpdySession::OnDataFrameHeader(spdy::SpdyStreamId stream_id,
  2864. size_t length,
  2865. bool fin) {
  2866. CHECK(in_io_loop_);
  2867. auto it = active_streams_.find(stream_id);
  2868. // By the time data comes in, the stream may already be inactive.
  2869. if (it == active_streams_.end())
  2870. return;
  2871. SpdyStream* stream = it->second;
  2872. CHECK_EQ(stream->stream_id(), stream_id);
  2873. DCHECK(buffered_spdy_framer_);
  2874. stream->AddRawReceivedBytes(spdy::kDataFrameMinimumSize);
  2875. }
  2876. void SpdySession::OnStreamFrameData(spdy::SpdyStreamId stream_id,
  2877. const char* data,
  2878. size_t len) {
  2879. CHECK(in_io_loop_);
  2880. DCHECK_LT(len, 1u << 24);
  2881. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_DATA, [&] {
  2882. return NetLogSpdyDataParams(stream_id, len, false);
  2883. });
  2884. // Build the buffer as early as possible so that we go through the
  2885. // session flow control checks and update
  2886. // |unacked_recv_window_bytes_| properly even when the stream is
  2887. // inactive (since the other side has still reduced its session send
  2888. // window).
  2889. std::unique_ptr<SpdyBuffer> buffer;
  2890. if (data) {
  2891. DCHECK_GT(len, 0u);
  2892. CHECK_LE(len, static_cast<size_t>(kReadBufferSize));
  2893. buffer = std::make_unique<SpdyBuffer>(data, len);
  2894. DecreaseRecvWindowSize(static_cast<int32_t>(len));
  2895. buffer->AddConsumeCallback(base::BindRepeating(
  2896. &SpdySession::OnReadBufferConsumed, weak_factory_.GetWeakPtr()));
  2897. } else {
  2898. DCHECK_EQ(len, 0u);
  2899. }
  2900. auto it = active_streams_.find(stream_id);
  2901. // By the time data comes in, the stream may already be inactive.
  2902. if (it == active_streams_.end())
  2903. return;
  2904. SpdyStream* stream = it->second;
  2905. CHECK_EQ(stream->stream_id(), stream_id);
  2906. stream->AddRawReceivedBytes(len);
  2907. stream->OnDataReceived(std::move(buffer));
  2908. }
  2909. void SpdySession::OnStreamEnd(spdy::SpdyStreamId stream_id) {
  2910. CHECK(in_io_loop_);
  2911. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_DATA,
  2912. [&] { return NetLogSpdyDataParams(stream_id, 0, true); });
  2913. auto it = active_streams_.find(stream_id);
  2914. // By the time data comes in, the stream may already be inactive.
  2915. if (it == active_streams_.end())
  2916. return;
  2917. SpdyStream* stream = it->second;
  2918. CHECK_EQ(stream->stream_id(), stream_id);
  2919. stream->OnDataReceived(std::unique_ptr<SpdyBuffer>());
  2920. }
  2921. void SpdySession::OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) {
  2922. CHECK(in_io_loop_);
  2923. // Decrease window size because padding bytes are received.
  2924. // Increase window size because padding bytes are consumed (by discarding).
  2925. // Net result: |session_unacked_recv_window_bytes_| increases by |len|,
  2926. // |session_recv_window_size_| does not change.
  2927. DecreaseRecvWindowSize(static_cast<int32_t>(len));
  2928. IncreaseRecvWindowSize(static_cast<int32_t>(len));
  2929. auto it = active_streams_.find(stream_id);
  2930. if (it == active_streams_.end())
  2931. return;
  2932. it->second->OnPaddingConsumed(len);
  2933. }
  2934. void SpdySession::OnSettings() {
  2935. CHECK(in_io_loop_);
  2936. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_SETTINGS);
  2937. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_SETTINGS_ACK);
  2938. // Send an acknowledgment of the setting.
  2939. spdy::SpdySettingsIR settings_ir;
  2940. settings_ir.set_is_ack(true);
  2941. auto frame = std::make_unique<spdy::SpdySerializedFrame>(
  2942. buffered_spdy_framer_->SerializeFrame(settings_ir));
  2943. EnqueueSessionWrite(HIGHEST, spdy::SpdyFrameType::SETTINGS, std::move(frame));
  2944. }
  2945. void SpdySession::OnSettingsAck() {
  2946. CHECK(in_io_loop_);
  2947. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_SETTINGS_ACK);
  2948. }
  2949. void SpdySession::OnSetting(spdy::SpdySettingsId id, uint32_t value) {
  2950. CHECK(in_io_loop_);
  2951. HandleSetting(id, value);
  2952. // Log the setting.
  2953. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_SETTING,
  2954. [&] { return NetLogSpdyRecvSettingParams(id, value); });
  2955. }
  2956. void SpdySession::OnSettingsEnd() {
  2957. settings_frame_received_ = true;
  2958. }
  2959. void SpdySession::OnWindowUpdate(spdy::SpdyStreamId stream_id,
  2960. int delta_window_size) {
  2961. CHECK(in_io_loop_);
  2962. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_WINDOW_UPDATE, [&] {
  2963. return NetLogSpdyWindowUpdateFrameParams(stream_id, delta_window_size);
  2964. });
  2965. if (stream_id == spdy::kSessionFlowControlStreamId) {
  2966. // WINDOW_UPDATE for the session.
  2967. if (delta_window_size < 1) {
  2968. RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE);
  2969. DoDrainSession(
  2970. ERR_HTTP2_PROTOCOL_ERROR,
  2971. "Received WINDOW_UPDATE with an invalid delta_window_size " +
  2972. base::NumberToString(delta_window_size));
  2973. return;
  2974. }
  2975. IncreaseSendWindowSize(delta_window_size);
  2976. } else {
  2977. // WINDOW_UPDATE for a stream.
  2978. auto it = active_streams_.find(stream_id);
  2979. if (it == active_streams_.end()) {
  2980. // NOTE: it may just be that the stream was cancelled.
  2981. LOG(WARNING) << "Received WINDOW_UPDATE for invalid stream " << stream_id;
  2982. return;
  2983. }
  2984. SpdyStream* stream = it->second;
  2985. CHECK_EQ(stream->stream_id(), stream_id);
  2986. if (delta_window_size < 1) {
  2987. ResetStreamIterator(
  2988. it, ERR_HTTP2_FLOW_CONTROL_ERROR,
  2989. "Received WINDOW_UPDATE with an invalid delta_window_size.");
  2990. return;
  2991. }
  2992. CHECK_EQ(it->second->stream_id(), stream_id);
  2993. it->second->IncreaseSendWindowSize(delta_window_size);
  2994. }
  2995. }
  2996. void SpdySession::OnPushPromise(spdy::SpdyStreamId stream_id,
  2997. spdy::SpdyStreamId promised_stream_id,
  2998. spdy::Http2HeaderBlock headers) {
  2999. CHECK(in_io_loop_);
  3000. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_PUSH_PROMISE,
  3001. [&](NetLogCaptureMode capture_mode) {
  3002. return NetLogSpdyPushPromiseReceivedParams(
  3003. &headers, stream_id, promised_stream_id,
  3004. capture_mode);
  3005. });
  3006. TryCreatePushStream(promised_stream_id, stream_id, std::move(headers));
  3007. }
  3008. void SpdySession::OnHeaders(spdy::SpdyStreamId stream_id,
  3009. bool has_priority,
  3010. int weight,
  3011. spdy::SpdyStreamId parent_stream_id,
  3012. bool exclusive,
  3013. bool fin,
  3014. spdy::Http2HeaderBlock headers,
  3015. base::TimeTicks recv_first_byte_time) {
  3016. CHECK(in_io_loop_);
  3017. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_HEADERS,
  3018. [&](NetLogCaptureMode capture_mode) {
  3019. return NetLogSpdyHeadersReceivedParams(
  3020. &headers, fin, stream_id, capture_mode);
  3021. });
  3022. auto it = active_streams_.find(stream_id);
  3023. if (it == active_streams_.end()) {
  3024. // NOTE: it may just be that the stream was cancelled.
  3025. LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id;
  3026. return;
  3027. }
  3028. SpdyStream* stream = it->second;
  3029. CHECK_EQ(stream->stream_id(), stream_id);
  3030. if (stream->type() == SPDY_PUSH_STREAM)
  3031. RecordPushedStreamVaryResponseHeaderHistogram(headers);
  3032. stream->AddRawReceivedBytes(last_compressed_frame_len_);
  3033. last_compressed_frame_len_ = 0;
  3034. if (it->second->IsReservedRemote()) {
  3035. DCHECK_EQ(SPDY_PUSH_STREAM, stream->type());
  3036. if (max_concurrent_pushed_streams_ &&
  3037. num_active_pushed_streams_ >= max_concurrent_pushed_streams_) {
  3038. RecordSpdyPushedStreamFateHistogram(
  3039. SpdyPushedStreamFate::kTooManyPushedStreams);
  3040. ResetStream(stream_id, ERR_HTTP2_CLIENT_REFUSED_STREAM,
  3041. "Stream concurrency limit reached.");
  3042. return;
  3043. }
  3044. // Will be balanced in DeleteStream.
  3045. num_active_pushed_streams_++;
  3046. }
  3047. base::Time response_time = base::Time::Now();
  3048. // May invalidate |stream|.
  3049. stream->OnHeadersReceived(headers, response_time, recv_first_byte_time);
  3050. }
  3051. void SpdySession::OnAltSvc(
  3052. spdy::SpdyStreamId stream_id,
  3053. base::StringPiece origin,
  3054. const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector) {
  3055. url::SchemeHostPort scheme_host_port;
  3056. if (stream_id == 0) {
  3057. if (origin.empty())
  3058. return;
  3059. const GURL gurl(origin);
  3060. if (!gurl.is_valid() || gurl.host().empty())
  3061. return;
  3062. if (!gurl.SchemeIs(url::kHttpsScheme))
  3063. return;
  3064. SSLInfo ssl_info;
  3065. if (!GetSSLInfo(&ssl_info))
  3066. return;
  3067. if (!CanPool(transport_security_state_, ssl_info, *ssl_config_service_,
  3068. host_port_pair().host(), gurl.host(),
  3069. spdy_session_key_.network_isolation_key())) {
  3070. return;
  3071. }
  3072. scheme_host_port = url::SchemeHostPort(gurl);
  3073. } else {
  3074. if (!origin.empty())
  3075. return;
  3076. const ActiveStreamMap::iterator it = active_streams_.find(stream_id);
  3077. if (it == active_streams_.end())
  3078. return;
  3079. const GURL& gurl(it->second->url());
  3080. if (!gurl.SchemeIs(url::kHttpsScheme))
  3081. return;
  3082. scheme_host_port = url::SchemeHostPort(gurl);
  3083. }
  3084. http_server_properties_->SetAlternativeServices(
  3085. scheme_host_port, spdy_session_key_.network_isolation_key(),
  3086. ProcessAlternativeServices(altsvc_vector, is_http2_enabled_,
  3087. is_quic_enabled_, quic_supported_versions_));
  3088. }
  3089. bool SpdySession::OnUnknownFrame(spdy::SpdyStreamId stream_id,
  3090. uint8_t frame_type) {
  3091. // Validate stream id.
  3092. // Was the frame sent on a stream id that has not been used in this session?
  3093. if (stream_id % 2 == 1 && stream_id > stream_hi_water_mark_)
  3094. return false;
  3095. if (stream_id % 2 == 0 && stream_id > last_accepted_push_stream_id_)
  3096. return false;
  3097. return true;
  3098. }
  3099. void SpdySession::OnSendCompressedFrame(spdy::SpdyStreamId stream_id,
  3100. spdy::SpdyFrameType type,
  3101. size_t payload_len,
  3102. size_t frame_len) {
  3103. if (type != spdy::SpdyFrameType::HEADERS) {
  3104. return;
  3105. }
  3106. DCHECK(buffered_spdy_framer_.get());
  3107. size_t compressed_len = frame_len - spdy::kFrameMinimumSize;
  3108. if (payload_len) {
  3109. // Make sure we avoid early decimal truncation.
  3110. int compression_pct = 100 - (100 * compressed_len) / payload_len;
  3111. UMA_HISTOGRAM_PERCENTAGE("Net.SpdyHeadersCompressionPercentage",
  3112. compression_pct);
  3113. }
  3114. }
  3115. void SpdySession::OnReceiveCompressedFrame(spdy::SpdyStreamId stream_id,
  3116. spdy::SpdyFrameType type,
  3117. size_t frame_len) {
  3118. last_compressed_frame_len_ = frame_len;
  3119. }
  3120. void SpdySession::OnWriteBufferConsumed(
  3121. size_t frame_payload_size,
  3122. size_t consume_size,
  3123. SpdyBuffer::ConsumeSource consume_source) {
  3124. // We can be called with |in_io_loop_| set if a write SpdyBuffer is
  3125. // deleted (e.g., a stream is closed due to incoming data).
  3126. if (consume_source == SpdyBuffer::DISCARD) {
  3127. // If we're discarding a frame or part of it, increase the send
  3128. // window by the number of discarded bytes. (Although if we're
  3129. // discarding part of a frame, it's probably because of a write
  3130. // error and we'll be tearing down the session soon.)
  3131. int remaining_payload_bytes = std::min(consume_size, frame_payload_size);
  3132. DCHECK_GT(remaining_payload_bytes, 0);
  3133. IncreaseSendWindowSize(remaining_payload_bytes);
  3134. }
  3135. // For consumed bytes, the send window is increased when we receive
  3136. // a WINDOW_UPDATE frame.
  3137. }
  3138. void SpdySession::IncreaseSendWindowSize(int delta_window_size) {
  3139. // We can be called with |in_io_loop_| set if a SpdyBuffer is
  3140. // deleted (e.g., a stream is closed due to incoming data).
  3141. DCHECK_GE(delta_window_size, 1);
  3142. // Check for overflow.
  3143. int32_t max_delta_window_size =
  3144. std::numeric_limits<int32_t>::max() - session_send_window_size_;
  3145. if (delta_window_size > max_delta_window_size) {
  3146. RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE);
  3147. DoDrainSession(
  3148. ERR_HTTP2_PROTOCOL_ERROR,
  3149. "Received WINDOW_UPDATE [delta: " +
  3150. base::NumberToString(delta_window_size) +
  3151. "] for session overflows session_send_window_size_ [current: " +
  3152. base::NumberToString(session_send_window_size_) + "]");
  3153. return;
  3154. }
  3155. session_send_window_size_ += delta_window_size;
  3156. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_UPDATE_SEND_WINDOW, [&] {
  3157. return NetLogSpdySessionWindowUpdateParams(delta_window_size,
  3158. session_send_window_size_);
  3159. });
  3160. DCHECK(!IsSendStalled());
  3161. ResumeSendStalledStreams();
  3162. }
  3163. void SpdySession::DecreaseSendWindowSize(int32_t delta_window_size) {
  3164. // We only call this method when sending a frame. Therefore,
  3165. // |delta_window_size| should be within the valid frame size range.
  3166. DCHECK_GE(delta_window_size, 1);
  3167. DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize);
  3168. // |send_window_size_| should have been at least |delta_window_size| for
  3169. // this call to happen.
  3170. DCHECK_GE(session_send_window_size_, delta_window_size);
  3171. session_send_window_size_ -= delta_window_size;
  3172. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_UPDATE_SEND_WINDOW, [&] {
  3173. return NetLogSpdySessionWindowUpdateParams(-delta_window_size,
  3174. session_send_window_size_);
  3175. });
  3176. }
  3177. void SpdySession::OnReadBufferConsumed(
  3178. size_t consume_size,
  3179. SpdyBuffer::ConsumeSource consume_source) {
  3180. // We can be called with |in_io_loop_| set if a read SpdyBuffer is
  3181. // deleted (e.g., discarded by a SpdyReadQueue).
  3182. DCHECK_GE(consume_size, 1u);
  3183. DCHECK_LE(consume_size,
  3184. static_cast<size_t>(std::numeric_limits<int32_t>::max()));
  3185. IncreaseRecvWindowSize(static_cast<int32_t>(consume_size));
  3186. }
  3187. void SpdySession::IncreaseRecvWindowSize(int32_t delta_window_size) {
  3188. DCHECK_GE(session_unacked_recv_window_bytes_, 0);
  3189. DCHECK_GE(session_recv_window_size_, session_unacked_recv_window_bytes_);
  3190. DCHECK_GE(delta_window_size, 1);
  3191. // Check for overflow.
  3192. DCHECK_LE(delta_window_size,
  3193. std::numeric_limits<int32_t>::max() - session_recv_window_size_);
  3194. session_recv_window_size_ += delta_window_size;
  3195. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_UPDATE_RECV_WINDOW, [&] {
  3196. return NetLogSpdySessionWindowUpdateParams(delta_window_size,
  3197. session_recv_window_size_);
  3198. });
  3199. // Update the receive window once half of the buffer is ready to be acked
  3200. // to prevent excessive window updates on fast downloads. Also send an update
  3201. // if too much time has elapsed since the last update to deal with
  3202. // slow-reading clients so the server doesn't think the session is idle.
  3203. session_unacked_recv_window_bytes_ += delta_window_size;
  3204. const base::TimeDelta elapsed =
  3205. base::TimeTicks::Now() - last_recv_window_update_;
  3206. if (session_unacked_recv_window_bytes_ > session_max_recv_window_size_ / 2 ||
  3207. elapsed >= time_to_buffer_small_window_updates_) {
  3208. last_recv_window_update_ = base::TimeTicks::Now();
  3209. SendWindowUpdateFrame(spdy::kSessionFlowControlStreamId,
  3210. session_unacked_recv_window_bytes_, HIGHEST);
  3211. session_unacked_recv_window_bytes_ = 0;
  3212. }
  3213. }
  3214. void SpdySession::DecreaseRecvWindowSize(int32_t delta_window_size) {
  3215. CHECK(in_io_loop_);
  3216. DCHECK_GE(delta_window_size, 1);
  3217. // The receiving window size as the peer knows it is
  3218. // |session_recv_window_size_ - session_unacked_recv_window_bytes_|, if more
  3219. // data are sent by the peer, that means that the receive window is not being
  3220. // respected.
  3221. int32_t receiving_window_size =
  3222. session_recv_window_size_ - session_unacked_recv_window_bytes_;
  3223. if (delta_window_size > receiving_window_size) {
  3224. RecordProtocolErrorHistogram(PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION);
  3225. DoDrainSession(
  3226. ERR_HTTP2_FLOW_CONTROL_ERROR,
  3227. "delta_window_size is " + base::NumberToString(delta_window_size) +
  3228. " in DecreaseRecvWindowSize, which is larger than the receive " +
  3229. "window size of " + base::NumberToString(receiving_window_size));
  3230. return;
  3231. }
  3232. session_recv_window_size_ -= delta_window_size;
  3233. net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_UPDATE_RECV_WINDOW, [&] {
  3234. return NetLogSpdySessionWindowUpdateParams(-delta_window_size,
  3235. session_recv_window_size_);
  3236. });
  3237. }
  3238. void SpdySession::QueueSendStalledStream(const SpdyStream& stream) {
  3239. DCHECK(stream.send_stalled_by_flow_control() || IsSendStalled());
  3240. RequestPriority priority = stream.priority();
  3241. CHECK_GE(priority, MINIMUM_PRIORITY);
  3242. CHECK_LE(priority, MAXIMUM_PRIORITY);
  3243. stream_send_unstall_queue_[priority].push_back(stream.stream_id());
  3244. }
  3245. void SpdySession::ResumeSendStalledStreams() {
  3246. // We don't have to worry about new streams being queued, since
  3247. // doing so would cause IsSendStalled() to return true. But we do
  3248. // have to worry about streams being closed, as well as ourselves
  3249. // being closed.
  3250. base::circular_deque<SpdyStream*> streams_to_requeue;
  3251. while (!IsSendStalled()) {
  3252. size_t old_size = 0;
  3253. #if DCHECK_IS_ON()
  3254. old_size = GetTotalSize(stream_send_unstall_queue_);
  3255. #endif
  3256. spdy::SpdyStreamId stream_id = PopStreamToPossiblyResume();
  3257. if (stream_id == 0)
  3258. break;
  3259. ActiveStreamMap::const_iterator it = active_streams_.find(stream_id);
  3260. // The stream may actually still be send-stalled after this (due
  3261. // to its own send window) but that's okay -- it'll then be
  3262. // resumed once its send window increases.
  3263. if (it != active_streams_.end()) {
  3264. if (it->second->PossiblyResumeIfSendStalled() == SpdyStream::Requeue)
  3265. streams_to_requeue.push_back(it->second);
  3266. }
  3267. // The size should decrease unless we got send-stalled again.
  3268. if (!IsSendStalled())
  3269. DCHECK_LT(GetTotalSize(stream_send_unstall_queue_), old_size);
  3270. }
  3271. while (!streams_to_requeue.empty()) {
  3272. SpdyStream* stream = streams_to_requeue.front();
  3273. streams_to_requeue.pop_front();
  3274. QueueSendStalledStream(*stream);
  3275. }
  3276. }
  3277. spdy::SpdyStreamId SpdySession::PopStreamToPossiblyResume() {
  3278. for (int i = MAXIMUM_PRIORITY; i >= MINIMUM_PRIORITY; --i) {
  3279. base::circular_deque<spdy::SpdyStreamId>* queue =
  3280. &stream_send_unstall_queue_[i];
  3281. if (!queue->empty()) {
  3282. spdy::SpdyStreamId stream_id = queue->front();
  3283. queue->pop_front();
  3284. return stream_id;
  3285. }
  3286. }
  3287. return 0;
  3288. }
  3289. void SpdySession::CheckConnectionStatus() {
  3290. MaybeSendPrefacePing();
  3291. // Also schedule the next check.
  3292. heartbeat_timer_.Start(
  3293. FROM_HERE, heartbeat_interval_,
  3294. base::BindOnce(&SpdySession::MaybeCheckConnectionStatus,
  3295. weak_factory_.GetWeakPtr()));
  3296. }
  3297. void SpdySession::OnDefaultNetworkActive() {
  3298. if (!check_connection_on_radio_wakeup_)
  3299. return;
  3300. check_connection_on_radio_wakeup_ = false;
  3301. CheckConnectionStatus();
  3302. }
  3303. void SpdySession::MaybeDisableBrokenConnectionDetection() {
  3304. DCHECK_GT(broken_connection_detection_requests_, 0);
  3305. DCHECK(IsBrokenConnectionDetectionEnabled());
  3306. if (--broken_connection_detection_requests_ > 0)
  3307. return;
  3308. heartbeat_timer_.Stop();
  3309. NetworkChangeNotifier::RemoveDefaultNetworkActiveObserver(this);
  3310. check_connection_on_radio_wakeup_ = false;
  3311. }
  3312. } // namespace net