nghttp2_session.c 253 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459
  1. /*
  2. * nghttp2 - HTTP/2 C Library
  3. *
  4. * Copyright (c) 2012 Tatsuhiro Tsujikawa
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "nghttp2_session.h"
  26. #include <string.h>
  27. #include <stddef.h>
  28. #include <stdio.h>
  29. #include <assert.h>
  30. #include <stdarg.h>
  31. #include "nghttp2_helper.h"
  32. #include "nghttp2_net.h"
  33. #include "nghttp2_priority_spec.h"
  34. #include "nghttp2_option.h"
  35. #include "nghttp2_http.h"
  36. #include "nghttp2_pq.h"
  37. #include "nghttp2_extpri.h"
  38. #include "nghttp2_time.h"
  39. #include "nghttp2_debug.h"
  40. #include "nghttp2_submit.h"
  41. /*
  42. * Returns non-zero if the number of outgoing opened streams is larger
  43. * than or equal to
  44. * remote_settings.max_concurrent_streams.
  45. */
  46. static int
  47. session_is_outgoing_concurrent_streams_max(nghttp2_session *session) {
  48. return session->remote_settings.max_concurrent_streams <=
  49. session->num_outgoing_streams;
  50. }
  51. /*
  52. * Returns non-zero if the number of incoming opened streams is larger
  53. * than or equal to
  54. * local_settings.max_concurrent_streams.
  55. */
  56. static int
  57. session_is_incoming_concurrent_streams_max(nghttp2_session *session) {
  58. return session->local_settings.max_concurrent_streams <=
  59. session->num_incoming_streams;
  60. }
  61. /*
  62. * Returns non-zero if the number of incoming opened streams is larger
  63. * than or equal to
  64. * session->pending_local_max_concurrent_stream.
  65. */
  66. static int
  67. session_is_incoming_concurrent_streams_pending_max(nghttp2_session *session) {
  68. return session->pending_local_max_concurrent_stream <=
  69. session->num_incoming_streams;
  70. }
  71. /*
  72. * Returns non-zero if |lib_error| is non-fatal error.
  73. */
  74. static int is_non_fatal(int lib_error_code) {
  75. return lib_error_code < 0 && lib_error_code > NGHTTP2_ERR_FATAL;
  76. }
  77. int nghttp2_is_fatal(int lib_error_code) {
  78. return lib_error_code < NGHTTP2_ERR_FATAL;
  79. }
  80. static int session_enforce_http_messaging(nghttp2_session *session) {
  81. return (session->opt_flags & NGHTTP2_OPTMASK_NO_HTTP_MESSAGING) == 0;
  82. }
  83. /*
  84. * Returns nonzero if |frame| is trailer headers.
  85. */
  86. static int session_trailer_headers(nghttp2_session *session,
  87. nghttp2_stream *stream,
  88. nghttp2_frame *frame) {
  89. if (!stream || frame->hd.type != NGHTTP2_HEADERS) {
  90. return 0;
  91. }
  92. if (session->server) {
  93. return frame->headers.cat == NGHTTP2_HCAT_HEADERS;
  94. }
  95. return frame->headers.cat == NGHTTP2_HCAT_HEADERS &&
  96. (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) == 0;
  97. }
  98. /* Returns nonzero if the |stream| is in reserved(remote) state */
  99. static int state_reserved_remote(nghttp2_session *session,
  100. nghttp2_stream *stream) {
  101. return stream->state == NGHTTP2_STREAM_RESERVED &&
  102. !nghttp2_session_is_my_stream_id(session, stream->stream_id);
  103. }
  104. /* Returns nonzero if the |stream| is in reserved(local) state */
  105. static int state_reserved_local(nghttp2_session *session,
  106. nghttp2_stream *stream) {
  107. return stream->state == NGHTTP2_STREAM_RESERVED &&
  108. nghttp2_session_is_my_stream_id(session, stream->stream_id);
  109. }
  110. /*
  111. * Checks whether received stream_id is valid. This function returns
  112. * 1 if it succeeds, or 0.
  113. */
  114. static int session_is_new_peer_stream_id(nghttp2_session *session,
  115. int32_t stream_id) {
  116. return stream_id != 0 &&
  117. !nghttp2_session_is_my_stream_id(session, stream_id) &&
  118. session->last_recv_stream_id < stream_id;
  119. }
  120. static int session_detect_idle_stream(nghttp2_session *session,
  121. int32_t stream_id) {
  122. /* Assume that stream object with stream_id does not exist */
  123. if (nghttp2_session_is_my_stream_id(session, stream_id)) {
  124. if (session->last_sent_stream_id < stream_id) {
  125. return 1;
  126. }
  127. return 0;
  128. }
  129. if (session_is_new_peer_stream_id(session, stream_id)) {
  130. return 1;
  131. }
  132. return 0;
  133. }
  134. static int session_no_rfc7540_pri_no_fallback(nghttp2_session *session) {
  135. return session->pending_no_rfc7540_priorities == 1 &&
  136. !session->fallback_rfc7540_priorities;
  137. }
  138. static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) {
  139. return (ext_types[type / 8] & (1 << (type & 0x7))) > 0;
  140. }
  141. static int session_call_error_callback(nghttp2_session *session,
  142. int lib_error_code, const char *fmt,
  143. ...) {
  144. size_t bufsize;
  145. va_list ap;
  146. char *buf;
  147. int rv;
  148. nghttp2_mem *mem;
  149. if (!session->callbacks.error_callback &&
  150. !session->callbacks.error_callback2) {
  151. return 0;
  152. }
  153. mem = &session->mem;
  154. va_start(ap, fmt);
  155. rv = vsnprintf(NULL, 0, fmt, ap);
  156. va_end(ap);
  157. if (rv < 0) {
  158. return NGHTTP2_ERR_NOMEM;
  159. }
  160. bufsize = (size_t)(rv + 1);
  161. buf = nghttp2_mem_malloc(mem, bufsize);
  162. if (buf == NULL) {
  163. return NGHTTP2_ERR_NOMEM;
  164. }
  165. va_start(ap, fmt);
  166. rv = vsnprintf(buf, bufsize, fmt, ap);
  167. va_end(ap);
  168. if (rv < 0) {
  169. nghttp2_mem_free(mem, buf);
  170. /* vsnprintf may return error because of various things we can
  171. imagine, but typically we don't want to drop session just for
  172. debug callback. */
  173. DEBUGF("error_callback: vsnprintf failed. The template was %s\n", fmt);
  174. return 0;
  175. }
  176. if (session->callbacks.error_callback2) {
  177. rv = session->callbacks.error_callback2(session, lib_error_code, buf,
  178. (size_t)rv, session->user_data);
  179. } else {
  180. rv = session->callbacks.error_callback(session, buf, (size_t)rv,
  181. session->user_data);
  182. }
  183. nghttp2_mem_free(mem, buf);
  184. if (rv != 0) {
  185. return NGHTTP2_ERR_CALLBACK_FAILURE;
  186. }
  187. return 0;
  188. }
  189. static int session_terminate_session(nghttp2_session *session,
  190. int32_t last_stream_id,
  191. uint32_t error_code, const char *reason) {
  192. int rv;
  193. const uint8_t *debug_data;
  194. size_t debug_datalen;
  195. if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
  196. return 0;
  197. }
  198. /* Ignore all incoming frames because we are going to tear down the
  199. session. */
  200. session->iframe.state = NGHTTP2_IB_IGN_ALL;
  201. if (reason == NULL) {
  202. debug_data = NULL;
  203. debug_datalen = 0;
  204. } else {
  205. debug_data = (const uint8_t *)reason;
  206. debug_datalen = strlen(reason);
  207. }
  208. rv =
  209. nghttp2_session_add_goaway(session, last_stream_id, error_code, debug_data,
  210. debug_datalen, NGHTTP2_GOAWAY_AUX_TERM_ON_SEND);
  211. if (rv != 0) {
  212. return rv;
  213. }
  214. session->goaway_flags |= NGHTTP2_GOAWAY_TERM_ON_SEND;
  215. return 0;
  216. }
  217. int nghttp2_session_terminate_session(nghttp2_session *session,
  218. uint32_t error_code) {
  219. return session_terminate_session(session, session->last_proc_stream_id,
  220. error_code, NULL);
  221. }
  222. int nghttp2_session_terminate_session2(nghttp2_session *session,
  223. int32_t last_stream_id,
  224. uint32_t error_code) {
  225. return session_terminate_session(session, last_stream_id, error_code, NULL);
  226. }
  227. int nghttp2_session_terminate_session_with_reason(nghttp2_session *session,
  228. uint32_t error_code,
  229. const char *reason) {
  230. return session_terminate_session(session, session->last_proc_stream_id,
  231. error_code, reason);
  232. }
  233. int nghttp2_session_is_my_stream_id(nghttp2_session *session,
  234. int32_t stream_id) {
  235. int rem;
  236. if (stream_id == 0) {
  237. return 0;
  238. }
  239. rem = stream_id & 0x1;
  240. if (session->server) {
  241. return rem == 0;
  242. }
  243. return rem == 1;
  244. }
  245. nghttp2_stream *nghttp2_session_get_stream(nghttp2_session *session,
  246. int32_t stream_id) {
  247. nghttp2_stream *stream;
  248. stream = (nghttp2_stream *)nghttp2_map_find(&session->streams, stream_id);
  249. if (stream == NULL || (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) ||
  250. stream->state == NGHTTP2_STREAM_IDLE) {
  251. return NULL;
  252. }
  253. return stream;
  254. }
  255. nghttp2_stream *nghttp2_session_get_stream_raw(nghttp2_session *session,
  256. int32_t stream_id) {
  257. return (nghttp2_stream *)nghttp2_map_find(&session->streams, stream_id);
  258. }
  259. static void session_inbound_frame_reset(nghttp2_session *session) {
  260. nghttp2_inbound_frame *iframe = &session->iframe;
  261. nghttp2_mem *mem = &session->mem;
  262. /* A bit risky code, since if this function is called from
  263. nghttp2_session_new(), we rely on the fact that
  264. iframe->frame.hd.type is 0, so that no free is performed. */
  265. switch (iframe->frame.hd.type) {
  266. case NGHTTP2_DATA:
  267. break;
  268. case NGHTTP2_HEADERS:
  269. nghttp2_frame_headers_free(&iframe->frame.headers, mem);
  270. break;
  271. case NGHTTP2_PRIORITY:
  272. nghttp2_frame_priority_free(&iframe->frame.priority);
  273. break;
  274. case NGHTTP2_RST_STREAM:
  275. nghttp2_frame_rst_stream_free(&iframe->frame.rst_stream);
  276. break;
  277. case NGHTTP2_SETTINGS:
  278. nghttp2_frame_settings_free(&iframe->frame.settings, mem);
  279. nghttp2_mem_free(mem, iframe->iv);
  280. iframe->iv = NULL;
  281. iframe->niv = 0;
  282. iframe->max_niv = 0;
  283. break;
  284. case NGHTTP2_PUSH_PROMISE:
  285. nghttp2_frame_push_promise_free(&iframe->frame.push_promise, mem);
  286. break;
  287. case NGHTTP2_PING:
  288. nghttp2_frame_ping_free(&iframe->frame.ping);
  289. break;
  290. case NGHTTP2_GOAWAY:
  291. nghttp2_frame_goaway_free(&iframe->frame.goaway, mem);
  292. break;
  293. case NGHTTP2_WINDOW_UPDATE:
  294. nghttp2_frame_window_update_free(&iframe->frame.window_update);
  295. break;
  296. default:
  297. /* extension frame */
  298. if (check_ext_type_set(session->user_recv_ext_types,
  299. iframe->frame.hd.type)) {
  300. nghttp2_frame_extension_free(&iframe->frame.ext);
  301. } else {
  302. switch (iframe->frame.hd.type) {
  303. case NGHTTP2_ALTSVC:
  304. if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) == 0) {
  305. break;
  306. }
  307. nghttp2_frame_altsvc_free(&iframe->frame.ext, mem);
  308. break;
  309. case NGHTTP2_ORIGIN:
  310. if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN) == 0) {
  311. break;
  312. }
  313. nghttp2_frame_origin_free(&iframe->frame.ext, mem);
  314. break;
  315. case NGHTTP2_PRIORITY_UPDATE:
  316. if ((session->builtin_recv_ext_types &
  317. NGHTTP2_TYPEMASK_PRIORITY_UPDATE) == 0) {
  318. break;
  319. }
  320. /* Do not call nghttp2_frame_priority_update_free, because all
  321. fields point to sbuf. */
  322. break;
  323. }
  324. }
  325. break;
  326. }
  327. memset(&iframe->frame, 0, sizeof(nghttp2_frame));
  328. memset(&iframe->ext_frame_payload, 0, sizeof(nghttp2_ext_frame_payload));
  329. iframe->state = NGHTTP2_IB_READ_HEAD;
  330. nghttp2_buf_wrap_init(&iframe->sbuf, iframe->raw_sbuf,
  331. sizeof(iframe->raw_sbuf));
  332. iframe->sbuf.mark += NGHTTP2_FRAME_HDLEN;
  333. nghttp2_buf_free(&iframe->lbuf, mem);
  334. nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
  335. iframe->raw_lbuf = NULL;
  336. iframe->payloadleft = 0;
  337. iframe->padlen = 0;
  338. }
  339. static void init_settings(nghttp2_settings_storage *settings) {
  340. settings->header_table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
  341. settings->enable_push = 1;
  342. settings->max_concurrent_streams = NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
  343. settings->initial_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
  344. settings->max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN;
  345. settings->max_header_list_size = UINT32_MAX;
  346. settings->no_rfc7540_priorities = UINT32_MAX;
  347. }
  348. static void active_outbound_item_reset(nghttp2_active_outbound_item *aob,
  349. nghttp2_mem *mem) {
  350. DEBUGF("send: reset nghttp2_active_outbound_item\n");
  351. DEBUGF("send: aob->item = %p\n", aob->item);
  352. nghttp2_outbound_item_free(aob->item, mem);
  353. nghttp2_mem_free(mem, aob->item);
  354. aob->item = NULL;
  355. nghttp2_bufs_reset(&aob->framebufs);
  356. aob->state = NGHTTP2_OB_POP_ITEM;
  357. }
  358. #define NGHTTP2_STREAM_MAX_CYCLE_GAP ((uint64_t)NGHTTP2_MAX_FRAME_SIZE_MAX)
  359. static int stream_less(const void *lhsx, const void *rhsx) {
  360. const nghttp2_stream *lhs, *rhs;
  361. lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry);
  362. rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry);
  363. if (lhs->cycle == rhs->cycle) {
  364. return lhs->seq < rhs->seq;
  365. }
  366. return rhs->cycle - lhs->cycle <= NGHTTP2_STREAM_MAX_CYCLE_GAP;
  367. }
  368. int nghttp2_enable_strict_preface = 1;
  369. static int session_new(nghttp2_session **session_ptr,
  370. const nghttp2_session_callbacks *callbacks,
  371. void *user_data, int server,
  372. const nghttp2_option *option, nghttp2_mem *mem) {
  373. int rv;
  374. size_t nbuffer;
  375. size_t max_deflate_dynamic_table_size =
  376. NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE;
  377. size_t i;
  378. if (mem == NULL) {
  379. mem = nghttp2_mem_default();
  380. }
  381. *session_ptr = nghttp2_mem_calloc(mem, 1, sizeof(nghttp2_session));
  382. if (*session_ptr == NULL) {
  383. rv = NGHTTP2_ERR_NOMEM;
  384. goto fail_session;
  385. }
  386. (*session_ptr)->mem = *mem;
  387. mem = &(*session_ptr)->mem;
  388. /* next_stream_id is initialized in either
  389. nghttp2_session_client_new2 or nghttp2_session_server_new2 */
  390. nghttp2_stream_init(&(*session_ptr)->root, 0, NGHTTP2_STREAM_FLAG_NONE,
  391. NGHTTP2_STREAM_IDLE, NGHTTP2_DEFAULT_WEIGHT, 0, 0, NULL,
  392. mem);
  393. (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
  394. (*session_ptr)->recv_window_size = 0;
  395. (*session_ptr)->consumed_size = 0;
  396. (*session_ptr)->recv_reduction = 0;
  397. (*session_ptr)->local_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
  398. (*session_ptr)->goaway_flags = NGHTTP2_GOAWAY_NONE;
  399. (*session_ptr)->local_last_stream_id = (1u << 31) - 1;
  400. (*session_ptr)->remote_last_stream_id = (1u << 31) - 1;
  401. (*session_ptr)->pending_local_max_concurrent_stream =
  402. NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
  403. (*session_ptr)->pending_enable_push = 1;
  404. (*session_ptr)->pending_no_rfc7540_priorities = UINT8_MAX;
  405. nghttp2_ratelim_init(&(*session_ptr)->stream_reset_ratelim,
  406. NGHTTP2_DEFAULT_STREAM_RESET_BURST,
  407. NGHTTP2_DEFAULT_STREAM_RESET_RATE);
  408. if (server) {
  409. (*session_ptr)->server = 1;
  410. }
  411. init_settings(&(*session_ptr)->remote_settings);
  412. init_settings(&(*session_ptr)->local_settings);
  413. (*session_ptr)->max_incoming_reserved_streams =
  414. NGHTTP2_MAX_INCOMING_RESERVED_STREAMS;
  415. /* Limit max outgoing concurrent streams to sensible value */
  416. (*session_ptr)->remote_settings.max_concurrent_streams = 100;
  417. (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
  418. (*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM;
  419. (*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS;
  420. (*session_ptr)->max_continuations = NGHTTP2_DEFAULT_MAX_CONTINUATIONS;
  421. if (option) {
  422. if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
  423. option->no_auto_window_update) {
  424. (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE;
  425. }
  426. if (option->opt_set_mask & NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS) {
  427. (*session_ptr)->remote_settings.max_concurrent_streams =
  428. option->peer_max_concurrent_streams;
  429. }
  430. if (option->opt_set_mask & NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS) {
  431. (*session_ptr)->max_incoming_reserved_streams =
  432. option->max_reserved_remote_streams;
  433. }
  434. if ((option->opt_set_mask & NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC) &&
  435. option->no_recv_client_magic) {
  436. (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC;
  437. }
  438. if ((option->opt_set_mask & NGHTTP2_OPT_NO_HTTP_MESSAGING) &&
  439. option->no_http_messaging) {
  440. (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
  441. }
  442. if (option->opt_set_mask & NGHTTP2_OPT_USER_RECV_EXT_TYPES) {
  443. memcpy((*session_ptr)->user_recv_ext_types, option->user_recv_ext_types,
  444. sizeof((*session_ptr)->user_recv_ext_types));
  445. }
  446. if (option->opt_set_mask & NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES) {
  447. (*session_ptr)->builtin_recv_ext_types = option->builtin_recv_ext_types;
  448. }
  449. if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_PING_ACK) &&
  450. option->no_auto_ping_ack) {
  451. (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_PING_ACK;
  452. }
  453. if (option->opt_set_mask & NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH) {
  454. (*session_ptr)->max_send_header_block_length =
  455. option->max_send_header_block_length;
  456. }
  457. if (option->opt_set_mask & NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE) {
  458. max_deflate_dynamic_table_size = option->max_deflate_dynamic_table_size;
  459. }
  460. if ((option->opt_set_mask & NGHTTP2_OPT_NO_CLOSED_STREAMS) &&
  461. option->no_closed_streams) {
  462. (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_CLOSED_STREAMS;
  463. }
  464. if (option->opt_set_mask & NGHTTP2_OPT_MAX_OUTBOUND_ACK) {
  465. (*session_ptr)->max_outbound_ack = option->max_outbound_ack;
  466. }
  467. if ((option->opt_set_mask & NGHTTP2_OPT_MAX_SETTINGS) &&
  468. option->max_settings) {
  469. (*session_ptr)->max_settings = option->max_settings;
  470. }
  471. if ((option->opt_set_mask &
  472. NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES) &&
  473. option->server_fallback_rfc7540_priorities) {
  474. (*session_ptr)->opt_flags |=
  475. NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES;
  476. }
  477. if ((option->opt_set_mask &
  478. NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) &&
  479. option->no_rfc9113_leading_and_trailing_ws_validation) {
  480. (*session_ptr)->opt_flags |=
  481. NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
  482. }
  483. if (option->opt_set_mask & NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT) {
  484. nghttp2_ratelim_init(&(*session_ptr)->stream_reset_ratelim,
  485. option->stream_reset_burst,
  486. option->stream_reset_rate);
  487. }
  488. if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) {
  489. (*session_ptr)->max_continuations = option->max_continuations;
  490. }
  491. }
  492. rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
  493. max_deflate_dynamic_table_size, mem);
  494. if (rv != 0) {
  495. goto fail_hd_deflater;
  496. }
  497. rv = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater, mem);
  498. if (rv != 0) {
  499. goto fail_hd_inflater;
  500. }
  501. nbuffer = ((*session_ptr)->max_send_header_block_length +
  502. NGHTTP2_FRAMEBUF_CHUNKLEN - 1) /
  503. NGHTTP2_FRAMEBUF_CHUNKLEN;
  504. if (nbuffer == 0) {
  505. nbuffer = 1;
  506. }
  507. /* 1 for Pad Field. */
  508. rv = nghttp2_bufs_init3(&(*session_ptr)->aob.framebufs,
  509. NGHTTP2_FRAMEBUF_CHUNKLEN, nbuffer, 1,
  510. NGHTTP2_FRAME_HDLEN + 1, mem);
  511. if (rv != 0) {
  512. goto fail_aob_framebuf;
  513. }
  514. nghttp2_map_init(&(*session_ptr)->streams, mem);
  515. active_outbound_item_reset(&(*session_ptr)->aob, mem);
  516. (*session_ptr)->callbacks = *callbacks;
  517. (*session_ptr)->user_data = user_data;
  518. session_inbound_frame_reset(*session_ptr);
  519. if (nghttp2_enable_strict_preface) {
  520. nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe;
  521. if (server && ((*session_ptr)->opt_flags &
  522. NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) == 0) {
  523. iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC;
  524. iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN;
  525. } else {
  526. iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS;
  527. }
  528. if (!server) {
  529. (*session_ptr)->aob.state = NGHTTP2_OB_SEND_CLIENT_MAGIC;
  530. nghttp2_bufs_add(&(*session_ptr)->aob.framebufs, NGHTTP2_CLIENT_MAGIC,
  531. NGHTTP2_CLIENT_MAGIC_LEN);
  532. }
  533. }
  534. for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
  535. nghttp2_pq_init(&(*session_ptr)->sched[i].ob_data, stream_less, mem);
  536. }
  537. return 0;
  538. fail_aob_framebuf:
  539. nghttp2_hd_inflate_free(&(*session_ptr)->hd_inflater);
  540. fail_hd_inflater:
  541. nghttp2_hd_deflate_free(&(*session_ptr)->hd_deflater);
  542. fail_hd_deflater:
  543. nghttp2_mem_free(mem, *session_ptr);
  544. fail_session:
  545. return rv;
  546. }
  547. int nghttp2_session_client_new(nghttp2_session **session_ptr,
  548. const nghttp2_session_callbacks *callbacks,
  549. void *user_data) {
  550. return nghttp2_session_client_new3(session_ptr, callbacks, user_data, NULL,
  551. NULL);
  552. }
  553. int nghttp2_session_client_new2(nghttp2_session **session_ptr,
  554. const nghttp2_session_callbacks *callbacks,
  555. void *user_data, const nghttp2_option *option) {
  556. return nghttp2_session_client_new3(session_ptr, callbacks, user_data, option,
  557. NULL);
  558. }
  559. int nghttp2_session_client_new3(nghttp2_session **session_ptr,
  560. const nghttp2_session_callbacks *callbacks,
  561. void *user_data, const nghttp2_option *option,
  562. nghttp2_mem *mem) {
  563. int rv;
  564. nghttp2_session *session;
  565. rv = session_new(&session, callbacks, user_data, 0, option, mem);
  566. if (rv != 0) {
  567. return rv;
  568. }
  569. /* IDs for use in client */
  570. session->next_stream_id = 1;
  571. *session_ptr = session;
  572. return 0;
  573. }
  574. int nghttp2_session_server_new(nghttp2_session **session_ptr,
  575. const nghttp2_session_callbacks *callbacks,
  576. void *user_data) {
  577. return nghttp2_session_server_new3(session_ptr, callbacks, user_data, NULL,
  578. NULL);
  579. }
  580. int nghttp2_session_server_new2(nghttp2_session **session_ptr,
  581. const nghttp2_session_callbacks *callbacks,
  582. void *user_data, const nghttp2_option *option) {
  583. return nghttp2_session_server_new3(session_ptr, callbacks, user_data, option,
  584. NULL);
  585. }
  586. int nghttp2_session_server_new3(nghttp2_session **session_ptr,
  587. const nghttp2_session_callbacks *callbacks,
  588. void *user_data, const nghttp2_option *option,
  589. nghttp2_mem *mem) {
  590. int rv;
  591. nghttp2_session *session;
  592. rv = session_new(&session, callbacks, user_data, 1, option, mem);
  593. if (rv != 0) {
  594. return rv;
  595. }
  596. /* IDs for use in client */
  597. session->next_stream_id = 2;
  598. *session_ptr = session;
  599. return 0;
  600. }
  601. static int free_streams(void *entry, void *ptr) {
  602. nghttp2_session *session;
  603. nghttp2_stream *stream;
  604. nghttp2_outbound_item *item;
  605. nghttp2_mem *mem;
  606. session = (nghttp2_session *)ptr;
  607. mem = &session->mem;
  608. stream = (nghttp2_stream *)entry;
  609. item = stream->item;
  610. if (item && !item->queued && item != session->aob.item) {
  611. nghttp2_outbound_item_free(item, mem);
  612. nghttp2_mem_free(mem, item);
  613. }
  614. nghttp2_stream_free(stream);
  615. nghttp2_mem_free(mem, stream);
  616. return 0;
  617. }
  618. static void ob_q_free(nghttp2_outbound_queue *q, nghttp2_mem *mem) {
  619. nghttp2_outbound_item *item, *next;
  620. for (item = q->head; item;) {
  621. next = item->qnext;
  622. nghttp2_outbound_item_free(item, mem);
  623. nghttp2_mem_free(mem, item);
  624. item = next;
  625. }
  626. }
  627. static int inflight_settings_new(nghttp2_inflight_settings **settings_ptr,
  628. const nghttp2_settings_entry *iv, size_t niv,
  629. nghttp2_mem *mem) {
  630. *settings_ptr = nghttp2_mem_malloc(mem, sizeof(nghttp2_inflight_settings));
  631. if (!*settings_ptr) {
  632. return NGHTTP2_ERR_NOMEM;
  633. }
  634. if (niv > 0) {
  635. (*settings_ptr)->iv = nghttp2_frame_iv_copy(iv, niv, mem);
  636. if (!(*settings_ptr)->iv) {
  637. nghttp2_mem_free(mem, *settings_ptr);
  638. return NGHTTP2_ERR_NOMEM;
  639. }
  640. } else {
  641. (*settings_ptr)->iv = NULL;
  642. }
  643. (*settings_ptr)->niv = niv;
  644. (*settings_ptr)->next = NULL;
  645. return 0;
  646. }
  647. static void inflight_settings_del(nghttp2_inflight_settings *settings,
  648. nghttp2_mem *mem) {
  649. if (!settings) {
  650. return;
  651. }
  652. nghttp2_mem_free(mem, settings->iv);
  653. nghttp2_mem_free(mem, settings);
  654. }
  655. void nghttp2_session_del(nghttp2_session *session) {
  656. nghttp2_mem *mem;
  657. nghttp2_inflight_settings *settings;
  658. size_t i;
  659. if (session == NULL) {
  660. return;
  661. }
  662. mem = &session->mem;
  663. for (settings = session->inflight_settings_head; settings;) {
  664. nghttp2_inflight_settings *next = settings->next;
  665. inflight_settings_del(settings, mem);
  666. settings = next;
  667. }
  668. for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
  669. nghttp2_pq_free(&session->sched[i].ob_data);
  670. }
  671. nghttp2_stream_free(&session->root);
  672. /* Have to free streams first, so that we can check
  673. stream->item->queued */
  674. nghttp2_map_each(&session->streams, free_streams, session);
  675. nghttp2_map_free(&session->streams);
  676. ob_q_free(&session->ob_urgent, mem);
  677. ob_q_free(&session->ob_reg, mem);
  678. ob_q_free(&session->ob_syn, mem);
  679. active_outbound_item_reset(&session->aob, mem);
  680. session_inbound_frame_reset(session);
  681. nghttp2_hd_deflate_free(&session->hd_deflater);
  682. nghttp2_hd_inflate_free(&session->hd_inflater);
  683. nghttp2_bufs_free(&session->aob.framebufs);
  684. nghttp2_mem_free(mem, session);
  685. }
  686. int nghttp2_session_reprioritize_stream(
  687. nghttp2_session *session, nghttp2_stream *stream,
  688. const nghttp2_priority_spec *pri_spec_in) {
  689. int rv;
  690. nghttp2_stream *dep_stream = NULL;
  691. nghttp2_priority_spec pri_spec_default;
  692. const nghttp2_priority_spec *pri_spec = pri_spec_in;
  693. assert((!session->server && session->pending_no_rfc7540_priorities != 1) ||
  694. (session->server && !session_no_rfc7540_pri_no_fallback(session)));
  695. assert(pri_spec->stream_id != stream->stream_id);
  696. if (!nghttp2_stream_in_dep_tree(stream)) {
  697. return 0;
  698. }
  699. if (pri_spec->stream_id != 0) {
  700. dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
  701. if (!dep_stream &&
  702. session_detect_idle_stream(session, pri_spec->stream_id)) {
  703. nghttp2_priority_spec_default_init(&pri_spec_default);
  704. dep_stream = nghttp2_session_open_stream(
  705. session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
  706. NGHTTP2_STREAM_IDLE, NULL);
  707. if (dep_stream == NULL) {
  708. return NGHTTP2_ERR_NOMEM;
  709. }
  710. } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
  711. nghttp2_priority_spec_default_init(&pri_spec_default);
  712. pri_spec = &pri_spec_default;
  713. }
  714. }
  715. if (pri_spec->stream_id == 0) {
  716. dep_stream = &session->root;
  717. } else if (nghttp2_stream_dep_find_ancestor(dep_stream, stream)) {
  718. DEBUGF("stream: cycle detected, dep_stream(%p)=%d stream(%p)=%d\n",
  719. dep_stream, dep_stream->stream_id, stream, stream->stream_id);
  720. nghttp2_stream_dep_remove_subtree(dep_stream);
  721. rv = nghttp2_stream_dep_add_subtree(stream->dep_prev, dep_stream);
  722. if (rv != 0) {
  723. return rv;
  724. }
  725. }
  726. assert(dep_stream);
  727. if (dep_stream == stream->dep_prev && !pri_spec->exclusive) {
  728. /* This is minor optimization when just weight is changed. */
  729. nghttp2_stream_change_weight(stream, pri_spec->weight);
  730. return 0;
  731. }
  732. nghttp2_stream_dep_remove_subtree(stream);
  733. /* We have to update weight after removing stream from tree */
  734. stream->weight = pri_spec->weight;
  735. if (pri_spec->exclusive) {
  736. rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream);
  737. } else {
  738. rv = nghttp2_stream_dep_add_subtree(dep_stream, stream);
  739. }
  740. if (rv != 0) {
  741. return rv;
  742. }
  743. return 0;
  744. }
  745. static uint64_t pq_get_first_cycle(nghttp2_pq *pq) {
  746. nghttp2_stream *stream;
  747. if (nghttp2_pq_empty(pq)) {
  748. return 0;
  749. }
  750. stream = nghttp2_struct_of(nghttp2_pq_top(pq), nghttp2_stream, pq_entry);
  751. return stream->cycle;
  752. }
  753. static int session_ob_data_push(nghttp2_session *session,
  754. nghttp2_stream *stream) {
  755. int rv;
  756. uint32_t urgency;
  757. int inc;
  758. nghttp2_pq *pq;
  759. assert(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
  760. assert(stream->queued == 0);
  761. urgency = nghttp2_extpri_uint8_urgency(stream->extpri);
  762. inc = nghttp2_extpri_uint8_inc(stream->extpri);
  763. assert(urgency < NGHTTP2_EXTPRI_URGENCY_LEVELS);
  764. pq = &session->sched[urgency].ob_data;
  765. stream->cycle = pq_get_first_cycle(pq);
  766. if (inc) {
  767. stream->cycle += stream->last_writelen;
  768. }
  769. rv = nghttp2_pq_push(pq, &stream->pq_entry);
  770. if (rv != 0) {
  771. return rv;
  772. }
  773. stream->queued = 1;
  774. return 0;
  775. }
  776. static void session_ob_data_remove(nghttp2_session *session,
  777. nghttp2_stream *stream) {
  778. uint32_t urgency;
  779. assert(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES);
  780. assert(stream->queued == 1);
  781. urgency = nghttp2_extpri_uint8_urgency(stream->extpri);
  782. assert(urgency < NGHTTP2_EXTPRI_URGENCY_LEVELS);
  783. nghttp2_pq_remove(&session->sched[urgency].ob_data, &stream->pq_entry);
  784. stream->queued = 0;
  785. }
  786. static int session_attach_stream_item(nghttp2_session *session,
  787. nghttp2_stream *stream,
  788. nghttp2_outbound_item *item) {
  789. int rv;
  790. rv = nghttp2_stream_attach_item(stream, item);
  791. if (rv != 0) {
  792. return rv;
  793. }
  794. if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) {
  795. return 0;
  796. }
  797. rv = session_ob_data_push(session, stream);
  798. if (rv != 0) {
  799. nghttp2_stream_detach_item(stream);
  800. return rv;
  801. }
  802. return 0;
  803. }
  804. static void session_detach_stream_item(nghttp2_session *session,
  805. nghttp2_stream *stream) {
  806. nghttp2_stream_detach_item(stream);
  807. if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
  808. !stream->queued) {
  809. return;
  810. }
  811. session_ob_data_remove(session, stream);
  812. }
  813. static void session_defer_stream_item(nghttp2_session *session,
  814. nghttp2_stream *stream, uint8_t flags) {
  815. nghttp2_stream_defer_item(stream, flags);
  816. if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
  817. !stream->queued) {
  818. return;
  819. }
  820. session_ob_data_remove(session, stream);
  821. }
  822. static int session_resume_deferred_stream_item(nghttp2_session *session,
  823. nghttp2_stream *stream,
  824. uint8_t flags) {
  825. int rv;
  826. rv = nghttp2_stream_resume_deferred_item(stream, flags);
  827. if (rv != 0) {
  828. return rv;
  829. }
  830. if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
  831. (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL)) {
  832. return 0;
  833. }
  834. return session_ob_data_push(session, stream);
  835. }
  836. static nghttp2_outbound_item *
  837. session_sched_get_next_outbound_item(nghttp2_session *session) {
  838. size_t i;
  839. nghttp2_pq_entry *ent;
  840. nghttp2_stream *stream;
  841. for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
  842. ent = nghttp2_pq_top(&session->sched[i].ob_data);
  843. if (!ent) {
  844. continue;
  845. }
  846. stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry);
  847. return stream->item;
  848. }
  849. return NULL;
  850. }
  851. static int session_sched_empty(nghttp2_session *session) {
  852. size_t i;
  853. for (i = 0; i < NGHTTP2_EXTPRI_URGENCY_LEVELS; ++i) {
  854. if (!nghttp2_pq_empty(&session->sched[i].ob_data)) {
  855. return 0;
  856. }
  857. }
  858. return 1;
  859. }
  860. static void session_sched_reschedule_stream(nghttp2_session *session,
  861. nghttp2_stream *stream) {
  862. nghttp2_pq *pq;
  863. uint32_t urgency = nghttp2_extpri_uint8_urgency(stream->extpri);
  864. int inc = nghttp2_extpri_uint8_inc(stream->extpri);
  865. uint64_t penalty = (uint64_t)stream->last_writelen;
  866. int rv;
  867. (void)rv;
  868. assert(urgency < NGHTTP2_EXTPRI_URGENCY_LEVELS);
  869. pq = &session->sched[urgency].ob_data;
  870. if (!inc || nghttp2_pq_size(pq) == 1) {
  871. return;
  872. }
  873. nghttp2_pq_remove(pq, &stream->pq_entry);
  874. stream->cycle += penalty;
  875. rv = nghttp2_pq_push(pq, &stream->pq_entry);
  876. assert(0 == rv);
  877. }
  878. static int session_update_stream_priority(nghttp2_session *session,
  879. nghttp2_stream *stream,
  880. uint8_t u8extpri) {
  881. if (stream->extpri == u8extpri) {
  882. return 0;
  883. }
  884. if (stream->queued) {
  885. session_ob_data_remove(session, stream);
  886. stream->extpri = u8extpri;
  887. return session_ob_data_push(session, stream);
  888. }
  889. stream->extpri = u8extpri;
  890. return 0;
  891. }
  892. int nghttp2_session_add_item(nghttp2_session *session,
  893. nghttp2_outbound_item *item) {
  894. /* TODO Return error if stream is not found for the frame requiring
  895. stream presence. */
  896. int rv = 0;
  897. nghttp2_stream *stream;
  898. nghttp2_frame *frame;
  899. frame = &item->frame;
  900. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  901. switch (frame->hd.type) {
  902. case NGHTTP2_DATA:
  903. if (!stream) {
  904. return NGHTTP2_ERR_STREAM_CLOSED;
  905. }
  906. if (stream->item) {
  907. return NGHTTP2_ERR_DATA_EXIST;
  908. }
  909. rv = session_attach_stream_item(session, stream, item);
  910. if (rv != 0) {
  911. return rv;
  912. }
  913. return 0;
  914. case NGHTTP2_HEADERS:
  915. /* We push request HEADERS and push response HEADERS to
  916. dedicated queue because their transmission is affected by
  917. SETTINGS_MAX_CONCURRENT_STREAMS */
  918. /* TODO If 2 HEADERS are submitted for reserved stream, then
  919. both of them are queued into ob_syn, which is not
  920. desirable. */
  921. if (frame->headers.cat == NGHTTP2_HCAT_REQUEST ||
  922. (stream && stream->state == NGHTTP2_STREAM_RESERVED)) {
  923. nghttp2_outbound_queue_push(&session->ob_syn, item);
  924. item->queued = 1;
  925. return 0;
  926. ;
  927. }
  928. nghttp2_outbound_queue_push(&session->ob_reg, item);
  929. item->queued = 1;
  930. return 0;
  931. case NGHTTP2_SETTINGS:
  932. case NGHTTP2_PING:
  933. nghttp2_outbound_queue_push(&session->ob_urgent, item);
  934. item->queued = 1;
  935. return 0;
  936. case NGHTTP2_RST_STREAM:
  937. if (stream) {
  938. stream->state = NGHTTP2_STREAM_CLOSING;
  939. }
  940. nghttp2_outbound_queue_push(&session->ob_reg, item);
  941. item->queued = 1;
  942. return 0;
  943. case NGHTTP2_PUSH_PROMISE: {
  944. nghttp2_headers_aux_data *aux_data;
  945. nghttp2_priority_spec pri_spec;
  946. aux_data = &item->aux_data.headers;
  947. if (!stream) {
  948. return NGHTTP2_ERR_STREAM_CLOSED;
  949. }
  950. nghttp2_priority_spec_init(&pri_spec, stream->stream_id,
  951. NGHTTP2_DEFAULT_WEIGHT, 0);
  952. if (!nghttp2_session_open_stream(
  953. session, frame->push_promise.promised_stream_id,
  954. NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_RESERVED,
  955. aux_data->stream_user_data)) {
  956. return NGHTTP2_ERR_NOMEM;
  957. }
  958. /* We don't have to call nghttp2_session_adjust_closed_stream()
  959. here, since stream->stream_id is local stream_id, and it does
  960. not affect closed stream count. */
  961. nghttp2_outbound_queue_push(&session->ob_reg, item);
  962. item->queued = 1;
  963. return 0;
  964. }
  965. case NGHTTP2_WINDOW_UPDATE:
  966. if (stream) {
  967. stream->window_update_queued = 1;
  968. } else if (frame->hd.stream_id == 0) {
  969. session->window_update_queued = 1;
  970. }
  971. nghttp2_outbound_queue_push(&session->ob_reg, item);
  972. item->queued = 1;
  973. return 0;
  974. default:
  975. nghttp2_outbound_queue_push(&session->ob_reg, item);
  976. item->queued = 1;
  977. return 0;
  978. }
  979. }
  980. int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
  981. uint32_t error_code) {
  982. int rv;
  983. nghttp2_outbound_item *item;
  984. nghttp2_frame *frame;
  985. nghttp2_stream *stream;
  986. nghttp2_mem *mem;
  987. mem = &session->mem;
  988. stream = nghttp2_session_get_stream(session, stream_id);
  989. if (stream && stream->state == NGHTTP2_STREAM_CLOSING) {
  990. return 0;
  991. }
  992. /* Sending RST_STREAM to an idle stream is subject to protocol
  993. violation. Historically, nghttp2 allows this. In order not to
  994. disrupt the existing applications, we don't error out this case
  995. and simply ignore it. */
  996. if (nghttp2_session_is_my_stream_id(session, stream_id)) {
  997. if ((uint32_t)stream_id >= session->next_stream_id) {
  998. return 0;
  999. }
  1000. } else if (session->last_recv_stream_id < stream_id) {
  1001. return 0;
  1002. }
  1003. /* Cancel pending request HEADERS in ob_syn if this RST_STREAM
  1004. refers to that stream. */
  1005. if (!session->server && nghttp2_session_is_my_stream_id(session, stream_id) &&
  1006. nghttp2_outbound_queue_top(&session->ob_syn)) {
  1007. nghttp2_headers_aux_data *aux_data;
  1008. nghttp2_frame *headers_frame;
  1009. headers_frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame;
  1010. assert(headers_frame->hd.type == NGHTTP2_HEADERS);
  1011. if (headers_frame->hd.stream_id <= stream_id) {
  1012. for (item = session->ob_syn.head; item; item = item->qnext) {
  1013. aux_data = &item->aux_data.headers;
  1014. if (item->frame.hd.stream_id < stream_id) {
  1015. continue;
  1016. }
  1017. /* stream_id in ob_syn queue must be strictly increasing. If
  1018. we found larger ID, then we can break here. */
  1019. if (item->frame.hd.stream_id > stream_id || aux_data->canceled) {
  1020. break;
  1021. }
  1022. aux_data->error_code = error_code;
  1023. aux_data->canceled = 1;
  1024. return 0;
  1025. }
  1026. }
  1027. }
  1028. item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  1029. if (item == NULL) {
  1030. return NGHTTP2_ERR_NOMEM;
  1031. }
  1032. nghttp2_outbound_item_init(item);
  1033. frame = &item->frame;
  1034. nghttp2_frame_rst_stream_init(&frame->rst_stream, stream_id, error_code);
  1035. rv = nghttp2_session_add_item(session, item);
  1036. if (rv != 0) {
  1037. nghttp2_frame_rst_stream_free(&frame->rst_stream);
  1038. nghttp2_mem_free(mem, item);
  1039. return rv;
  1040. }
  1041. return 0;
  1042. }
  1043. nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
  1044. int32_t stream_id, uint8_t flags,
  1045. nghttp2_priority_spec *pri_spec_in,
  1046. nghttp2_stream_state initial_state,
  1047. void *stream_user_data) {
  1048. int rv;
  1049. nghttp2_stream *stream;
  1050. nghttp2_stream *dep_stream = NULL;
  1051. int stream_alloc = 0;
  1052. nghttp2_priority_spec pri_spec_default;
  1053. nghttp2_priority_spec *pri_spec = pri_spec_in;
  1054. nghttp2_mem *mem;
  1055. mem = &session->mem;
  1056. stream = nghttp2_session_get_stream_raw(session, stream_id);
  1057. if (session->opt_flags &
  1058. NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
  1059. flags |= NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
  1060. }
  1061. if (stream) {
  1062. assert(stream->state == NGHTTP2_STREAM_IDLE);
  1063. assert((stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) ||
  1064. nghttp2_stream_in_dep_tree(stream));
  1065. nghttp2_session_detach_idle_stream(session, stream);
  1066. if (nghttp2_stream_in_dep_tree(stream)) {
  1067. assert(!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES));
  1068. rv = nghttp2_stream_dep_remove(stream);
  1069. if (rv != 0) {
  1070. return NULL;
  1071. }
  1072. if (session_no_rfc7540_pri_no_fallback(session)) {
  1073. stream->flags |= NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES;
  1074. }
  1075. }
  1076. } else {
  1077. stream = nghttp2_mem_malloc(mem, sizeof(nghttp2_stream));
  1078. if (stream == NULL) {
  1079. return NULL;
  1080. }
  1081. stream_alloc = 1;
  1082. }
  1083. if (session_no_rfc7540_pri_no_fallback(session) ||
  1084. session->remote_settings.no_rfc7540_priorities == 1) {
  1085. /* For client which has not received server
  1086. SETTINGS_NO_RFC7540_PRIORITIES = 1, send a priority signal
  1087. opportunistically. */
  1088. if (session->server ||
  1089. session->remote_settings.no_rfc7540_priorities == 1) {
  1090. nghttp2_priority_spec_default_init(&pri_spec_default);
  1091. pri_spec = &pri_spec_default;
  1092. }
  1093. if (session->pending_no_rfc7540_priorities == 1) {
  1094. flags |= NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES;
  1095. }
  1096. } else if (pri_spec->stream_id != 0) {
  1097. dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
  1098. if (!dep_stream &&
  1099. session_detect_idle_stream(session, pri_spec->stream_id)) {
  1100. /* Depends on idle stream, which does not exist in memory.
  1101. Assign default priority for it. */
  1102. nghttp2_priority_spec_default_init(&pri_spec_default);
  1103. dep_stream = nghttp2_session_open_stream(
  1104. session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
  1105. NGHTTP2_STREAM_IDLE, NULL);
  1106. if (dep_stream == NULL) {
  1107. if (stream_alloc) {
  1108. nghttp2_mem_free(mem, stream);
  1109. }
  1110. return NULL;
  1111. }
  1112. } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
  1113. /* If dep_stream is not part of dependency tree, stream will get
  1114. default priority. This handles the case when
  1115. pri_spec->stream_id == stream_id. This happens because we
  1116. don't check pri_spec->stream_id against new stream ID in
  1117. nghttp2_submit_request. This also handles the case when idle
  1118. stream created by PRIORITY frame was opened. Somehow we
  1119. first remove the idle stream from dependency tree. This is
  1120. done to simplify code base, but ideally we should retain old
  1121. dependency. But I'm not sure this adds values. */
  1122. nghttp2_priority_spec_default_init(&pri_spec_default);
  1123. pri_spec = &pri_spec_default;
  1124. }
  1125. }
  1126. if (initial_state == NGHTTP2_STREAM_RESERVED) {
  1127. flags |= NGHTTP2_STREAM_FLAG_PUSH;
  1128. }
  1129. if (stream_alloc) {
  1130. nghttp2_stream_init(stream, stream_id, flags, initial_state,
  1131. pri_spec->weight,
  1132. (int32_t)session->remote_settings.initial_window_size,
  1133. (int32_t)session->local_settings.initial_window_size,
  1134. stream_user_data, mem);
  1135. if (session_no_rfc7540_pri_no_fallback(session)) {
  1136. stream->seq = session->stream_seq++;
  1137. }
  1138. rv = nghttp2_map_insert(&session->streams, stream_id, stream);
  1139. if (rv != 0) {
  1140. nghttp2_stream_free(stream);
  1141. nghttp2_mem_free(mem, stream);
  1142. return NULL;
  1143. }
  1144. } else {
  1145. stream->flags = flags;
  1146. stream->state = initial_state;
  1147. stream->weight = pri_spec->weight;
  1148. stream->stream_user_data = stream_user_data;
  1149. }
  1150. switch (initial_state) {
  1151. case NGHTTP2_STREAM_RESERVED:
  1152. if (nghttp2_session_is_my_stream_id(session, stream_id)) {
  1153. /* reserved (local) */
  1154. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
  1155. } else {
  1156. /* reserved (remote) */
  1157. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
  1158. ++session->num_incoming_reserved_streams;
  1159. }
  1160. /* Reserved stream does not count in the concurrent streams
  1161. limit. That is one of the DOS vector. */
  1162. break;
  1163. case NGHTTP2_STREAM_IDLE:
  1164. /* Idle stream does not count toward the concurrent streams limit.
  1165. This is used as anchor node in dependency tree. */
  1166. nghttp2_session_keep_idle_stream(session, stream);
  1167. break;
  1168. default:
  1169. if (nghttp2_session_is_my_stream_id(session, stream_id)) {
  1170. ++session->num_outgoing_streams;
  1171. } else {
  1172. ++session->num_incoming_streams;
  1173. }
  1174. }
  1175. if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
  1176. return stream;
  1177. }
  1178. if (pri_spec->stream_id == 0) {
  1179. dep_stream = &session->root;
  1180. }
  1181. assert(dep_stream);
  1182. if (pri_spec->exclusive) {
  1183. rv = nghttp2_stream_dep_insert(dep_stream, stream);
  1184. if (rv != 0) {
  1185. return NULL;
  1186. }
  1187. } else {
  1188. nghttp2_stream_dep_add(dep_stream, stream);
  1189. }
  1190. return stream;
  1191. }
  1192. int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
  1193. uint32_t error_code) {
  1194. int rv;
  1195. nghttp2_stream *stream;
  1196. nghttp2_mem *mem;
  1197. int is_my_stream_id;
  1198. mem = &session->mem;
  1199. stream = nghttp2_session_get_stream(session, stream_id);
  1200. if (!stream) {
  1201. return NGHTTP2_ERR_INVALID_ARGUMENT;
  1202. }
  1203. DEBUGF("stream: stream(%p)=%d close\n", stream, stream->stream_id);
  1204. /* We call on_stream_close_callback even if stream->state is
  1205. NGHTTP2_STREAM_INITIAL. This will happen while sending request
  1206. HEADERS, a local endpoint receives RST_STREAM for that stream. It
  1207. may be PROTOCOL_ERROR, but without notifying stream closure will
  1208. hang the stream in a local endpoint.
  1209. */
  1210. if (session->callbacks.on_stream_close_callback) {
  1211. if (session->callbacks.on_stream_close_callback(
  1212. session, stream_id, error_code, session->user_data) != 0) {
  1213. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1214. }
  1215. }
  1216. if (stream->item) {
  1217. nghttp2_outbound_item *item;
  1218. item = stream->item;
  1219. session_detach_stream_item(session, stream);
  1220. /* If item is queued, it will be deleted when it is popped
  1221. (nghttp2_session_prep_frame() will fail). If session->aob.item
  1222. points to this item, let active_outbound_item_reset()
  1223. free the item. */
  1224. if (!item->queued && item != session->aob.item) {
  1225. nghttp2_outbound_item_free(item, mem);
  1226. nghttp2_mem_free(mem, item);
  1227. }
  1228. }
  1229. is_my_stream_id = nghttp2_session_is_my_stream_id(session, stream_id);
  1230. /* pushed streams which is not opened yet is not counted toward max
  1231. concurrent limits */
  1232. if ((stream->flags & NGHTTP2_STREAM_FLAG_PUSH)) {
  1233. if (!is_my_stream_id) {
  1234. --session->num_incoming_reserved_streams;
  1235. }
  1236. } else {
  1237. if (is_my_stream_id) {
  1238. --session->num_outgoing_streams;
  1239. } else {
  1240. --session->num_incoming_streams;
  1241. }
  1242. }
  1243. /* Closes both directions just in case they are not closed yet */
  1244. stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED;
  1245. if (session->pending_no_rfc7540_priorities == 1) {
  1246. return nghttp2_session_destroy_stream(session, stream);
  1247. }
  1248. if ((session->opt_flags & NGHTTP2_OPTMASK_NO_CLOSED_STREAMS) == 0 &&
  1249. session->server && !is_my_stream_id &&
  1250. nghttp2_stream_in_dep_tree(stream)) {
  1251. /* On server side, retain stream at most MAX_CONCURRENT_STREAMS
  1252. combined with the current active incoming streams to make
  1253. dependency tree work better. */
  1254. nghttp2_session_keep_closed_stream(session, stream);
  1255. } else {
  1256. rv = nghttp2_session_destroy_stream(session, stream);
  1257. if (rv != 0) {
  1258. return rv;
  1259. }
  1260. }
  1261. return 0;
  1262. }
  1263. int nghttp2_session_destroy_stream(nghttp2_session *session,
  1264. nghttp2_stream *stream) {
  1265. nghttp2_mem *mem;
  1266. int rv;
  1267. DEBUGF("stream: destroy closed stream(%p)=%d\n", stream, stream->stream_id);
  1268. mem = &session->mem;
  1269. if (nghttp2_stream_in_dep_tree(stream)) {
  1270. rv = nghttp2_stream_dep_remove(stream);
  1271. if (rv != 0) {
  1272. return rv;
  1273. }
  1274. }
  1275. if (stream->queued &&
  1276. (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) {
  1277. session_ob_data_remove(session, stream);
  1278. }
  1279. nghttp2_map_remove(&session->streams, stream->stream_id);
  1280. nghttp2_stream_free(stream);
  1281. nghttp2_mem_free(mem, stream);
  1282. return 0;
  1283. }
  1284. void nghttp2_session_keep_closed_stream(nghttp2_session *session,
  1285. nghttp2_stream *stream) {
  1286. DEBUGF("stream: keep closed stream(%p)=%d, state=%d\n", stream,
  1287. stream->stream_id, stream->state);
  1288. if (session->closed_stream_tail) {
  1289. session->closed_stream_tail->closed_next = stream;
  1290. stream->closed_prev = session->closed_stream_tail;
  1291. } else {
  1292. session->closed_stream_head = stream;
  1293. }
  1294. session->closed_stream_tail = stream;
  1295. ++session->num_closed_streams;
  1296. }
  1297. void nghttp2_session_keep_idle_stream(nghttp2_session *session,
  1298. nghttp2_stream *stream) {
  1299. DEBUGF("stream: keep idle stream(%p)=%d, state=%d\n", stream,
  1300. stream->stream_id, stream->state);
  1301. if (session->idle_stream_tail) {
  1302. session->idle_stream_tail->closed_next = stream;
  1303. stream->closed_prev = session->idle_stream_tail;
  1304. } else {
  1305. session->idle_stream_head = stream;
  1306. }
  1307. session->idle_stream_tail = stream;
  1308. ++session->num_idle_streams;
  1309. }
  1310. void nghttp2_session_detach_idle_stream(nghttp2_session *session,
  1311. nghttp2_stream *stream) {
  1312. nghttp2_stream *prev_stream, *next_stream;
  1313. DEBUGF("stream: detach idle stream(%p)=%d, state=%d\n", stream,
  1314. stream->stream_id, stream->state);
  1315. prev_stream = stream->closed_prev;
  1316. next_stream = stream->closed_next;
  1317. if (prev_stream) {
  1318. prev_stream->closed_next = next_stream;
  1319. } else {
  1320. session->idle_stream_head = next_stream;
  1321. }
  1322. if (next_stream) {
  1323. next_stream->closed_prev = prev_stream;
  1324. } else {
  1325. session->idle_stream_tail = prev_stream;
  1326. }
  1327. stream->closed_prev = NULL;
  1328. stream->closed_next = NULL;
  1329. --session->num_idle_streams;
  1330. }
  1331. int nghttp2_session_adjust_closed_stream(nghttp2_session *session) {
  1332. size_t num_stream_max;
  1333. int rv;
  1334. if (session->local_settings.max_concurrent_streams ==
  1335. NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS) {
  1336. num_stream_max = session->pending_local_max_concurrent_stream;
  1337. } else {
  1338. num_stream_max = session->local_settings.max_concurrent_streams;
  1339. }
  1340. DEBUGF("stream: adjusting kept closed streams num_closed_streams=%zu, "
  1341. "num_incoming_streams=%zu, max_concurrent_streams=%zu\n",
  1342. session->num_closed_streams, session->num_incoming_streams,
  1343. num_stream_max);
  1344. while (session->num_closed_streams > 0 &&
  1345. session->num_closed_streams + session->num_incoming_streams >
  1346. num_stream_max) {
  1347. nghttp2_stream *head_stream;
  1348. nghttp2_stream *next;
  1349. head_stream = session->closed_stream_head;
  1350. assert(head_stream);
  1351. next = head_stream->closed_next;
  1352. rv = nghttp2_session_destroy_stream(session, head_stream);
  1353. if (rv != 0) {
  1354. return rv;
  1355. }
  1356. /* head_stream is now freed */
  1357. session->closed_stream_head = next;
  1358. if (session->closed_stream_head) {
  1359. session->closed_stream_head->closed_prev = NULL;
  1360. } else {
  1361. session->closed_stream_tail = NULL;
  1362. }
  1363. --session->num_closed_streams;
  1364. }
  1365. return 0;
  1366. }
  1367. int nghttp2_session_adjust_idle_stream(nghttp2_session *session) {
  1368. size_t max;
  1369. int rv;
  1370. /* Make minimum number of idle streams 16, and maximum 100, which
  1371. are arbitrary chosen numbers. */
  1372. max = nghttp2_min_uint32(
  1373. 100,
  1374. nghttp2_max_uint32(
  1375. 16, nghttp2_min_uint32(session->local_settings.max_concurrent_streams,
  1376. session->pending_local_max_concurrent_stream)));
  1377. DEBUGF("stream: adjusting kept idle streams num_idle_streams=%zu, max=%zu\n",
  1378. session->num_idle_streams, max);
  1379. while (session->num_idle_streams > max) {
  1380. nghttp2_stream *head;
  1381. nghttp2_stream *next;
  1382. head = session->idle_stream_head;
  1383. assert(head);
  1384. next = head->closed_next;
  1385. rv = nghttp2_session_destroy_stream(session, head);
  1386. if (rv != 0) {
  1387. return rv;
  1388. }
  1389. /* head is now destroyed */
  1390. session->idle_stream_head = next;
  1391. if (session->idle_stream_head) {
  1392. session->idle_stream_head->closed_prev = NULL;
  1393. } else {
  1394. session->idle_stream_tail = NULL;
  1395. }
  1396. --session->num_idle_streams;
  1397. }
  1398. return 0;
  1399. }
  1400. /*
  1401. * Closes stream with stream ID |stream_id| if both transmission and
  1402. * reception of the stream were disallowed. The |error_code| indicates
  1403. * the reason of the closure.
  1404. *
  1405. * This function returns 0 if it succeeds, or one of the following
  1406. * negative error codes:
  1407. *
  1408. * NGHTTP2_ERR_INVALID_ARGUMENT
  1409. * The stream is not found.
  1410. * NGHTTP2_ERR_CALLBACK_FAILURE
  1411. * The callback function failed.
  1412. */
  1413. int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session,
  1414. nghttp2_stream *stream) {
  1415. if ((stream->shut_flags & NGHTTP2_SHUT_RDWR) == NGHTTP2_SHUT_RDWR) {
  1416. return nghttp2_session_close_stream(session, stream->stream_id,
  1417. NGHTTP2_NO_ERROR);
  1418. }
  1419. return 0;
  1420. }
  1421. /*
  1422. * Returns nonzero if local endpoint allows reception of new stream
  1423. * from remote.
  1424. */
  1425. static int session_allow_incoming_new_stream(nghttp2_session *session) {
  1426. return (session->goaway_flags &
  1427. (NGHTTP2_GOAWAY_TERM_ON_SEND | NGHTTP2_GOAWAY_SENT)) == 0;
  1428. }
  1429. /*
  1430. * This function returns nonzero if session is closing.
  1431. */
  1432. static int session_is_closing(nghttp2_session *session) {
  1433. return (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) != 0 ||
  1434. (nghttp2_session_want_read(session) == 0 &&
  1435. nghttp2_session_want_write(session) == 0);
  1436. }
  1437. /*
  1438. * Check that we can send a frame to the |stream|. This function
  1439. * returns 0 if we can send a frame to the |frame|, or one of the
  1440. * following negative error codes:
  1441. *
  1442. * NGHTTP2_ERR_STREAM_CLOSED
  1443. * The stream is already closed.
  1444. * NGHTTP2_ERR_STREAM_SHUT_WR
  1445. * The stream is half-closed for transmission.
  1446. * NGHTTP2_ERR_SESSION_CLOSING
  1447. * This session is closing.
  1448. */
  1449. static int session_predicate_for_stream_send(nghttp2_session *session,
  1450. nghttp2_stream *stream) {
  1451. if (stream == NULL) {
  1452. return NGHTTP2_ERR_STREAM_CLOSED;
  1453. }
  1454. if (session_is_closing(session)) {
  1455. return NGHTTP2_ERR_SESSION_CLOSING;
  1456. }
  1457. if (stream->shut_flags & NGHTTP2_SHUT_WR) {
  1458. return NGHTTP2_ERR_STREAM_SHUT_WR;
  1459. }
  1460. return 0;
  1461. }
  1462. int nghttp2_session_check_request_allowed(nghttp2_session *session) {
  1463. return !session->server && session->next_stream_id <= INT32_MAX &&
  1464. (session->goaway_flags & NGHTTP2_GOAWAY_RECV) == 0 &&
  1465. !session_is_closing(session);
  1466. }
  1467. /*
  1468. * This function checks request HEADERS frame, which opens stream, can
  1469. * be sent at this time.
  1470. *
  1471. * This function returns 0 if it succeeds, or one of the following
  1472. * negative error codes:
  1473. *
  1474. * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
  1475. * New stream cannot be created because of GOAWAY: session is
  1476. * going down or received last_stream_id is strictly less than
  1477. * frame->hd.stream_id.
  1478. * NGHTTP2_ERR_STREAM_CLOSING
  1479. * request HEADERS was canceled by RST_STREAM while it is in queue.
  1480. */
  1481. static int session_predicate_request_headers_send(nghttp2_session *session,
  1482. nghttp2_outbound_item *item) {
  1483. if (item->aux_data.headers.canceled) {
  1484. return NGHTTP2_ERR_STREAM_CLOSING;
  1485. }
  1486. /* If we are terminating session (NGHTTP2_GOAWAY_TERM_ON_SEND),
  1487. GOAWAY was received from peer, or session is about to close, new
  1488. request is not allowed. */
  1489. if ((session->goaway_flags & NGHTTP2_GOAWAY_RECV) ||
  1490. session_is_closing(session)) {
  1491. return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
  1492. }
  1493. return 0;
  1494. }
  1495. /*
  1496. * This function checks HEADERS, which is the first frame from the
  1497. * server, with the |stream| can be sent at this time. The |stream|
  1498. * can be NULL.
  1499. *
  1500. * This function returns 0 if it succeeds, or one of the following
  1501. * negative error codes:
  1502. *
  1503. * NGHTTP2_ERR_STREAM_CLOSED
  1504. * The stream is already closed or does not exist.
  1505. * NGHTTP2_ERR_STREAM_SHUT_WR
  1506. * The transmission is not allowed for this stream (e.g., a frame
  1507. * with END_STREAM flag set has already sent)
  1508. * NGHTTP2_ERR_INVALID_STREAM_ID
  1509. * The stream ID is invalid.
  1510. * NGHTTP2_ERR_STREAM_CLOSING
  1511. * RST_STREAM was queued for this stream.
  1512. * NGHTTP2_ERR_INVALID_STREAM_STATE
  1513. * The state of the stream is not valid.
  1514. * NGHTTP2_ERR_SESSION_CLOSING
  1515. * This session is closing.
  1516. * NGHTTP2_ERR_PROTO
  1517. * Client side attempted to send response.
  1518. */
  1519. static int session_predicate_response_headers_send(nghttp2_session *session,
  1520. nghttp2_stream *stream) {
  1521. int rv;
  1522. rv = session_predicate_for_stream_send(session, stream);
  1523. if (rv != 0) {
  1524. return rv;
  1525. }
  1526. assert(stream);
  1527. if (!session->server) {
  1528. return NGHTTP2_ERR_PROTO;
  1529. }
  1530. if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
  1531. return NGHTTP2_ERR_INVALID_STREAM_ID;
  1532. }
  1533. switch (stream->state) {
  1534. case NGHTTP2_STREAM_OPENING:
  1535. return 0;
  1536. case NGHTTP2_STREAM_CLOSING:
  1537. return NGHTTP2_ERR_STREAM_CLOSING;
  1538. default:
  1539. return NGHTTP2_ERR_INVALID_STREAM_STATE;
  1540. }
  1541. }
  1542. /*
  1543. * This function checks HEADERS for reserved stream can be sent. The
  1544. * |stream| must be reserved state and the |session| is server side.
  1545. * The |stream| can be NULL.
  1546. *
  1547. * This function returns 0 if it succeeds, or one of the following
  1548. * error codes:
  1549. *
  1550. * NGHTTP2_ERR_STREAM_CLOSED
  1551. * The stream is already closed.
  1552. * NGHTTP2_ERR_STREAM_SHUT_WR
  1553. * The stream is half-closed for transmission.
  1554. * NGHTTP2_ERR_PROTO
  1555. * The stream is not reserved state
  1556. * NGHTTP2_ERR_STREAM_CLOSED
  1557. * RST_STREAM was queued for this stream.
  1558. * NGHTTP2_ERR_SESSION_CLOSING
  1559. * This session is closing.
  1560. * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
  1561. * New stream cannot be created because GOAWAY is already sent or
  1562. * received.
  1563. * NGHTTP2_ERR_PROTO
  1564. * Client side attempted to send push response.
  1565. */
  1566. static int
  1567. session_predicate_push_response_headers_send(nghttp2_session *session,
  1568. nghttp2_stream *stream) {
  1569. int rv;
  1570. /* TODO Should disallow HEADERS if GOAWAY has already been issued? */
  1571. rv = session_predicate_for_stream_send(session, stream);
  1572. if (rv != 0) {
  1573. return rv;
  1574. }
  1575. assert(stream);
  1576. if (!session->server) {
  1577. return NGHTTP2_ERR_PROTO;
  1578. }
  1579. if (stream->state != NGHTTP2_STREAM_RESERVED) {
  1580. return NGHTTP2_ERR_PROTO;
  1581. }
  1582. if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) {
  1583. return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
  1584. }
  1585. return 0;
  1586. }
  1587. /*
  1588. * This function checks HEADERS, which is neither stream-opening nor
  1589. * first response header, with the |stream| can be sent at this time.
  1590. * The |stream| can be NULL.
  1591. *
  1592. * This function returns 0 if it succeeds, or one of the following
  1593. * negative error codes:
  1594. *
  1595. * NGHTTP2_ERR_STREAM_CLOSED
  1596. * The stream is already closed or does not exist.
  1597. * NGHTTP2_ERR_STREAM_SHUT_WR
  1598. * The transmission is not allowed for this stream (e.g., a frame
  1599. * with END_STREAM flag set has already sent)
  1600. * NGHTTP2_ERR_STREAM_CLOSING
  1601. * RST_STREAM was queued for this stream.
  1602. * NGHTTP2_ERR_INVALID_STREAM_STATE
  1603. * The state of the stream is not valid.
  1604. * NGHTTP2_ERR_SESSION_CLOSING
  1605. * This session is closing.
  1606. */
  1607. static int session_predicate_headers_send(nghttp2_session *session,
  1608. nghttp2_stream *stream) {
  1609. int rv;
  1610. rv = session_predicate_for_stream_send(session, stream);
  1611. if (rv != 0) {
  1612. return rv;
  1613. }
  1614. assert(stream);
  1615. switch (stream->state) {
  1616. case NGHTTP2_STREAM_OPENED:
  1617. return 0;
  1618. case NGHTTP2_STREAM_CLOSING:
  1619. return NGHTTP2_ERR_STREAM_CLOSING;
  1620. default:
  1621. if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
  1622. return 0;
  1623. }
  1624. return NGHTTP2_ERR_INVALID_STREAM_STATE;
  1625. }
  1626. }
  1627. /*
  1628. * This function checks PUSH_PROMISE frame |frame| with the |stream|
  1629. * can be sent at this time. The |stream| can be NULL.
  1630. *
  1631. * This function returns 0 if it succeeds, or one of the following
  1632. * negative error codes:
  1633. *
  1634. * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
  1635. * New stream cannot be created because GOAWAY is already sent or
  1636. * received.
  1637. * NGHTTP2_ERR_PROTO
  1638. * The client side attempts to send PUSH_PROMISE, or the server
  1639. * sends PUSH_PROMISE for the stream not initiated by the client.
  1640. * NGHTTP2_ERR_STREAM_CLOSED
  1641. * The stream is already closed or does not exist.
  1642. * NGHTTP2_ERR_STREAM_CLOSING
  1643. * RST_STREAM was queued for this stream.
  1644. * NGHTTP2_ERR_STREAM_SHUT_WR
  1645. * The transmission is not allowed for this stream (e.g., a frame
  1646. * with END_STREAM flag set has already sent)
  1647. * NGHTTP2_ERR_PUSH_DISABLED
  1648. * The remote peer disabled reception of PUSH_PROMISE.
  1649. * NGHTTP2_ERR_SESSION_CLOSING
  1650. * This session is closing.
  1651. */
  1652. static int session_predicate_push_promise_send(nghttp2_session *session,
  1653. nghttp2_stream *stream) {
  1654. int rv;
  1655. if (!session->server) {
  1656. return NGHTTP2_ERR_PROTO;
  1657. }
  1658. rv = session_predicate_for_stream_send(session, stream);
  1659. if (rv != 0) {
  1660. return rv;
  1661. }
  1662. assert(stream);
  1663. if (session->remote_settings.enable_push == 0) {
  1664. return NGHTTP2_ERR_PUSH_DISABLED;
  1665. }
  1666. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  1667. return NGHTTP2_ERR_STREAM_CLOSING;
  1668. }
  1669. if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) {
  1670. return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
  1671. }
  1672. return 0;
  1673. }
  1674. /*
  1675. * This function checks WINDOW_UPDATE with the stream ID |stream_id|
  1676. * can be sent at this time. Note that END_STREAM flag of the previous
  1677. * frame does not affect the transmission of the WINDOW_UPDATE frame.
  1678. *
  1679. * This function returns 0 if it succeeds, or one of the following
  1680. * negative error codes:
  1681. *
  1682. * NGHTTP2_ERR_STREAM_CLOSED
  1683. * The stream is already closed or does not exist.
  1684. * NGHTTP2_ERR_STREAM_CLOSING
  1685. * RST_STREAM was queued for this stream.
  1686. * NGHTTP2_ERR_INVALID_STREAM_STATE
  1687. * The state of the stream is not valid.
  1688. * NGHTTP2_ERR_SESSION_CLOSING
  1689. * This session is closing.
  1690. */
  1691. static int session_predicate_window_update_send(nghttp2_session *session,
  1692. int32_t stream_id) {
  1693. nghttp2_stream *stream;
  1694. if (session_is_closing(session)) {
  1695. return NGHTTP2_ERR_SESSION_CLOSING;
  1696. }
  1697. if (stream_id == 0) {
  1698. /* Connection-level window update */
  1699. return 0;
  1700. }
  1701. stream = nghttp2_session_get_stream(session, stream_id);
  1702. if (stream == NULL) {
  1703. return NGHTTP2_ERR_STREAM_CLOSED;
  1704. }
  1705. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  1706. return NGHTTP2_ERR_STREAM_CLOSING;
  1707. }
  1708. if (state_reserved_local(session, stream)) {
  1709. return NGHTTP2_ERR_INVALID_STREAM_STATE;
  1710. }
  1711. return 0;
  1712. }
  1713. static int session_predicate_altsvc_send(nghttp2_session *session,
  1714. int32_t stream_id) {
  1715. nghttp2_stream *stream;
  1716. if (session_is_closing(session)) {
  1717. return NGHTTP2_ERR_SESSION_CLOSING;
  1718. }
  1719. if (stream_id == 0) {
  1720. return 0;
  1721. }
  1722. stream = nghttp2_session_get_stream(session, stream_id);
  1723. if (stream == NULL) {
  1724. return NGHTTP2_ERR_STREAM_CLOSED;
  1725. }
  1726. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  1727. return NGHTTP2_ERR_STREAM_CLOSING;
  1728. }
  1729. return 0;
  1730. }
  1731. static int session_predicate_origin_send(nghttp2_session *session) {
  1732. if (session_is_closing(session)) {
  1733. return NGHTTP2_ERR_SESSION_CLOSING;
  1734. }
  1735. return 0;
  1736. }
  1737. static int session_predicate_priority_update_send(nghttp2_session *session,
  1738. int32_t stream_id) {
  1739. nghttp2_stream *stream;
  1740. if (session_is_closing(session)) {
  1741. return NGHTTP2_ERR_SESSION_CLOSING;
  1742. }
  1743. stream = nghttp2_session_get_stream(session, stream_id);
  1744. if (stream == NULL) {
  1745. return 0;
  1746. }
  1747. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  1748. return NGHTTP2_ERR_STREAM_CLOSING;
  1749. }
  1750. if (stream->shut_flags & NGHTTP2_SHUT_RD) {
  1751. return NGHTTP2_ERR_INVALID_STREAM_STATE;
  1752. }
  1753. return 0;
  1754. }
  1755. /* Take into account settings max frame size and both connection-level
  1756. flow control here */
  1757. static nghttp2_ssize nghttp2_session_enforce_flow_control_limits(
  1758. nghttp2_session *session, nghttp2_stream *stream,
  1759. nghttp2_ssize requested_window_size) {
  1760. DEBUGF("send: remote windowsize connection=%d, remote maxframsize=%u, "
  1761. "stream(id %d)=%d\n",
  1762. session->remote_window_size, session->remote_settings.max_frame_size,
  1763. stream->stream_id, stream->remote_window_size);
  1764. return nghttp2_min_int32(
  1765. nghttp2_min_int32(nghttp2_min_int32((int32_t)requested_window_size,
  1766. stream->remote_window_size),
  1767. session->remote_window_size),
  1768. (int32_t)session->remote_settings.max_frame_size);
  1769. }
  1770. /*
  1771. * Returns the maximum length of next data read. If the
  1772. * connection-level and/or stream-wise flow control are enabled, the
  1773. * return value takes into account those current window sizes. The remote
  1774. * settings for max frame size is also taken into account.
  1775. */
  1776. static size_t nghttp2_session_next_data_read(nghttp2_session *session,
  1777. nghttp2_stream *stream) {
  1778. nghttp2_ssize window_size;
  1779. window_size = nghttp2_session_enforce_flow_control_limits(
  1780. session, stream, NGHTTP2_DATA_PAYLOADLEN);
  1781. DEBUGF("send: available window=%td\n", window_size);
  1782. return window_size > 0 ? (size_t)window_size : 0;
  1783. }
  1784. /*
  1785. * This function checks DATA with the |stream| can be sent at this
  1786. * time. The |stream| can be NULL.
  1787. *
  1788. * This function returns 0 if it succeeds, or one of the following
  1789. * negative error codes:
  1790. *
  1791. * NGHTTP2_ERR_STREAM_CLOSED
  1792. * The stream is already closed or does not exist.
  1793. * NGHTTP2_ERR_STREAM_SHUT_WR
  1794. * The transmission is not allowed for this stream (e.g., a frame
  1795. * with END_STREAM flag set has already sent)
  1796. * NGHTTP2_ERR_STREAM_CLOSING
  1797. * RST_STREAM was queued for this stream.
  1798. * NGHTTP2_ERR_INVALID_STREAM_STATE
  1799. * The state of the stream is not valid.
  1800. * NGHTTP2_ERR_SESSION_CLOSING
  1801. * This session is closing.
  1802. */
  1803. static int nghttp2_session_predicate_data_send(nghttp2_session *session,
  1804. nghttp2_stream *stream) {
  1805. int rv;
  1806. rv = session_predicate_for_stream_send(session, stream);
  1807. if (rv != 0) {
  1808. return rv;
  1809. }
  1810. assert(stream);
  1811. if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
  1812. /* Request body data */
  1813. /* If stream->state is NGHTTP2_STREAM_CLOSING, RST_STREAM was
  1814. queued but not yet sent. In this case, we won't send DATA
  1815. frames. */
  1816. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  1817. return NGHTTP2_ERR_STREAM_CLOSING;
  1818. }
  1819. if (stream->state == NGHTTP2_STREAM_RESERVED) {
  1820. return NGHTTP2_ERR_INVALID_STREAM_STATE;
  1821. }
  1822. return 0;
  1823. }
  1824. /* Response body data */
  1825. if (stream->state == NGHTTP2_STREAM_OPENED) {
  1826. return 0;
  1827. }
  1828. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  1829. return NGHTTP2_ERR_STREAM_CLOSING;
  1830. }
  1831. return NGHTTP2_ERR_INVALID_STREAM_STATE;
  1832. }
  1833. static nghttp2_ssize session_call_select_padding(nghttp2_session *session,
  1834. const nghttp2_frame *frame,
  1835. size_t max_payloadlen) {
  1836. nghttp2_ssize rv;
  1837. size_t max_paddedlen;
  1838. if (frame->hd.length >= max_payloadlen ||
  1839. (!session->callbacks.select_padding_callback2 &&
  1840. !session->callbacks.select_padding_callback)) {
  1841. return (nghttp2_ssize)frame->hd.length;
  1842. }
  1843. max_paddedlen =
  1844. nghttp2_min_size(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen);
  1845. if (session->callbacks.select_padding_callback2) {
  1846. rv = session->callbacks.select_padding_callback2(
  1847. session, frame, max_paddedlen, session->user_data);
  1848. } else {
  1849. rv = (nghttp2_ssize)session->callbacks.select_padding_callback(
  1850. session, frame, max_paddedlen, session->user_data);
  1851. }
  1852. if (rv < (nghttp2_ssize)frame->hd.length ||
  1853. rv > (nghttp2_ssize)max_paddedlen) {
  1854. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1855. }
  1856. return rv;
  1857. }
  1858. /* Add padding to HEADERS or PUSH_PROMISE. We use
  1859. frame->headers.padlen in this function to use the fact that
  1860. frame->push_promise has also padlen in the same position. */
  1861. static int session_headers_add_pad(nghttp2_session *session,
  1862. nghttp2_frame *frame) {
  1863. nghttp2_ssize padded_payloadlen;
  1864. nghttp2_active_outbound_item *aob;
  1865. nghttp2_bufs *framebufs;
  1866. size_t padlen;
  1867. size_t max_payloadlen;
  1868. aob = &session->aob;
  1869. framebufs = &aob->framebufs;
  1870. max_payloadlen = nghttp2_min_size(NGHTTP2_MAX_PAYLOADLEN,
  1871. frame->hd.length + NGHTTP2_MAX_PADLEN);
  1872. padded_payloadlen =
  1873. session_call_select_padding(session, frame, max_payloadlen);
  1874. if (nghttp2_is_fatal((int)padded_payloadlen)) {
  1875. return (int)padded_payloadlen;
  1876. }
  1877. padlen = (size_t)padded_payloadlen - frame->hd.length;
  1878. DEBUGF("send: padding selected: payloadlen=%td, padlen=%zu\n",
  1879. padded_payloadlen, padlen);
  1880. nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0);
  1881. frame->headers.padlen = padlen;
  1882. return 0;
  1883. }
  1884. static size_t session_estimate_headers_payload(nghttp2_session *session,
  1885. const nghttp2_nv *nva,
  1886. size_t nvlen,
  1887. size_t additional) {
  1888. return nghttp2_hd_deflate_bound(&session->hd_deflater, nva, nvlen) +
  1889. additional;
  1890. }
  1891. static int session_pack_extension(nghttp2_session *session, nghttp2_bufs *bufs,
  1892. nghttp2_frame *frame) {
  1893. nghttp2_ssize rv;
  1894. nghttp2_buf *buf;
  1895. size_t buflen;
  1896. size_t framelen;
  1897. assert(session->callbacks.pack_extension_callback2 ||
  1898. session->callbacks.pack_extension_callback);
  1899. buf = &bufs->head->buf;
  1900. buflen = nghttp2_min_size(nghttp2_buf_avail(buf), NGHTTP2_MAX_PAYLOADLEN);
  1901. if (session->callbacks.pack_extension_callback2) {
  1902. rv = session->callbacks.pack_extension_callback2(session, buf->last, buflen,
  1903. frame, session->user_data);
  1904. } else {
  1905. rv = (nghttp2_ssize)session->callbacks.pack_extension_callback(
  1906. session, buf->last, buflen, frame, session->user_data);
  1907. }
  1908. if (rv == NGHTTP2_ERR_CANCEL) {
  1909. return (int)rv;
  1910. }
  1911. if (rv < 0 || (size_t)rv > buflen) {
  1912. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1913. }
  1914. framelen = (size_t)rv;
  1915. frame->hd.length = framelen;
  1916. assert(buf->pos == buf->last);
  1917. buf->last += framelen;
  1918. buf->pos -= NGHTTP2_FRAME_HDLEN;
  1919. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  1920. return 0;
  1921. }
  1922. /*
  1923. * This function serializes frame for transmission.
  1924. *
  1925. * This function returns 0 if it succeeds, or one of negative error
  1926. * codes, including both fatal and non-fatal ones.
  1927. */
  1928. static int session_prep_frame(nghttp2_session *session,
  1929. nghttp2_outbound_item *item) {
  1930. int rv;
  1931. nghttp2_frame *frame;
  1932. nghttp2_mem *mem;
  1933. mem = &session->mem;
  1934. frame = &item->frame;
  1935. switch (frame->hd.type) {
  1936. case NGHTTP2_DATA: {
  1937. size_t next_readmax;
  1938. nghttp2_stream *stream;
  1939. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  1940. if (stream) {
  1941. assert(stream->item == item);
  1942. }
  1943. rv = nghttp2_session_predicate_data_send(session, stream);
  1944. if (rv != 0) {
  1945. // If stream was already closed, nghttp2_session_get_stream()
  1946. // returns NULL, but item is still attached to the stream.
  1947. // Search stream including closed again.
  1948. stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
  1949. if (stream) {
  1950. session_detach_stream_item(session, stream);
  1951. }
  1952. return rv;
  1953. }
  1954. /* Assuming stream is not NULL */
  1955. assert(stream);
  1956. next_readmax = nghttp2_session_next_data_read(session, stream);
  1957. if (next_readmax == 0) {
  1958. /* This must be true since we only pop DATA frame item from
  1959. queue when session->remote_window_size > 0 */
  1960. assert(session->remote_window_size > 0);
  1961. session_defer_stream_item(session, stream,
  1962. NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
  1963. session->aob.item = NULL;
  1964. active_outbound_item_reset(&session->aob, mem);
  1965. return NGHTTP2_ERR_DEFERRED;
  1966. }
  1967. rv =
  1968. nghttp2_session_pack_data(session, &session->aob.framebufs, next_readmax,
  1969. frame, &item->aux_data.data, stream);
  1970. if (rv == NGHTTP2_ERR_PAUSE) {
  1971. return rv;
  1972. }
  1973. if (rv == NGHTTP2_ERR_DEFERRED) {
  1974. session_defer_stream_item(session, stream,
  1975. NGHTTP2_STREAM_FLAG_DEFERRED_USER);
  1976. session->aob.item = NULL;
  1977. active_outbound_item_reset(&session->aob, mem);
  1978. return NGHTTP2_ERR_DEFERRED;
  1979. }
  1980. if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  1981. session_detach_stream_item(session, stream);
  1982. rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id,
  1983. NGHTTP2_INTERNAL_ERROR);
  1984. if (nghttp2_is_fatal(rv)) {
  1985. return rv;
  1986. }
  1987. return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
  1988. }
  1989. if (rv != 0) {
  1990. session_detach_stream_item(session, stream);
  1991. return rv;
  1992. }
  1993. return 0;
  1994. }
  1995. case NGHTTP2_HEADERS: {
  1996. nghttp2_headers_aux_data *aux_data;
  1997. size_t estimated_payloadlen;
  1998. aux_data = &item->aux_data.headers;
  1999. if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
  2000. /* initial HEADERS, which opens stream */
  2001. nghttp2_stream *stream;
  2002. stream = nghttp2_session_open_stream(
  2003. session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE,
  2004. &frame->headers.pri_spec, NGHTTP2_STREAM_INITIAL,
  2005. aux_data->stream_user_data);
  2006. if (stream == NULL) {
  2007. return NGHTTP2_ERR_NOMEM;
  2008. }
  2009. /* We don't call nghttp2_session_adjust_closed_stream() here,
  2010. since we don't keep closed stream in client side */
  2011. rv = session_predicate_request_headers_send(session, item);
  2012. if (rv != 0) {
  2013. return rv;
  2014. }
  2015. if (session_enforce_http_messaging(session)) {
  2016. nghttp2_http_record_request_method(stream, frame);
  2017. }
  2018. } else {
  2019. nghttp2_stream *stream;
  2020. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  2021. if (stream && stream->state == NGHTTP2_STREAM_RESERVED) {
  2022. rv = session_predicate_push_response_headers_send(session, stream);
  2023. if (rv == 0) {
  2024. frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE;
  2025. if (aux_data->stream_user_data) {
  2026. stream->stream_user_data = aux_data->stream_user_data;
  2027. }
  2028. }
  2029. } else if (session_predicate_response_headers_send(session, stream) ==
  2030. 0) {
  2031. frame->headers.cat = NGHTTP2_HCAT_RESPONSE;
  2032. rv = 0;
  2033. } else {
  2034. frame->headers.cat = NGHTTP2_HCAT_HEADERS;
  2035. rv = session_predicate_headers_send(session, stream);
  2036. }
  2037. if (rv != 0) {
  2038. return rv;
  2039. }
  2040. }
  2041. estimated_payloadlen = session_estimate_headers_payload(
  2042. session, frame->headers.nva, frame->headers.nvlen,
  2043. NGHTTP2_PRIORITY_SPECLEN);
  2044. if (estimated_payloadlen > session->max_send_header_block_length) {
  2045. return NGHTTP2_ERR_FRAME_SIZE_ERROR;
  2046. }
  2047. rv = nghttp2_frame_pack_headers(&session->aob.framebufs, &frame->headers,
  2048. &session->hd_deflater);
  2049. if (rv != 0) {
  2050. return rv;
  2051. }
  2052. DEBUGF("send: before padding, HEADERS serialized in %zu bytes\n",
  2053. nghttp2_bufs_len(&session->aob.framebufs));
  2054. rv = session_headers_add_pad(session, frame);
  2055. if (rv != 0) {
  2056. return rv;
  2057. }
  2058. DEBUGF("send: HEADERS finally serialized in %zu bytes\n",
  2059. nghttp2_bufs_len(&session->aob.framebufs));
  2060. if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
  2061. assert(session->last_sent_stream_id < frame->hd.stream_id);
  2062. session->last_sent_stream_id = frame->hd.stream_id;
  2063. }
  2064. return 0;
  2065. }
  2066. case NGHTTP2_PRIORITY: {
  2067. if (session_is_closing(session)) {
  2068. return NGHTTP2_ERR_SESSION_CLOSING;
  2069. }
  2070. /* PRIORITY frame can be sent at any time and to any stream
  2071. ID. */
  2072. nghttp2_frame_pack_priority(&session->aob.framebufs, &frame->priority);
  2073. /* Peer can send PRIORITY frame against idle stream to create
  2074. "anchor" in dependency tree. Only client can do this in
  2075. nghttp2. In nghttp2, only server retains non-active (closed
  2076. or idle) streams in memory, so we don't open stream here. */
  2077. return 0;
  2078. }
  2079. case NGHTTP2_RST_STREAM:
  2080. if (session_is_closing(session)) {
  2081. return NGHTTP2_ERR_SESSION_CLOSING;
  2082. }
  2083. nghttp2_frame_pack_rst_stream(&session->aob.framebufs, &frame->rst_stream);
  2084. return 0;
  2085. case NGHTTP2_SETTINGS: {
  2086. if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
  2087. assert(session->obq_flood_counter_ > 0);
  2088. --session->obq_flood_counter_;
  2089. /* When session is about to close, don't send SETTINGS ACK.
  2090. We are required to send SETTINGS without ACK though; for
  2091. example, we have to send SETTINGS as a part of connection
  2092. preface. */
  2093. if (session_is_closing(session)) {
  2094. return NGHTTP2_ERR_SESSION_CLOSING;
  2095. }
  2096. }
  2097. rv = nghttp2_frame_pack_settings(&session->aob.framebufs, &frame->settings);
  2098. if (rv != 0) {
  2099. return rv;
  2100. }
  2101. return 0;
  2102. }
  2103. case NGHTTP2_PUSH_PROMISE: {
  2104. nghttp2_stream *stream;
  2105. size_t estimated_payloadlen;
  2106. /* stream could be NULL if associated stream was already
  2107. closed. */
  2108. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  2109. /* predicate should fail if stream is NULL. */
  2110. rv = session_predicate_push_promise_send(session, stream);
  2111. if (rv != 0) {
  2112. return rv;
  2113. }
  2114. assert(stream);
  2115. estimated_payloadlen = session_estimate_headers_payload(
  2116. session, frame->push_promise.nva, frame->push_promise.nvlen, 0);
  2117. if (estimated_payloadlen > session->max_send_header_block_length) {
  2118. return NGHTTP2_ERR_FRAME_SIZE_ERROR;
  2119. }
  2120. rv = nghttp2_frame_pack_push_promise(
  2121. &session->aob.framebufs, &frame->push_promise, &session->hd_deflater);
  2122. if (rv != 0) {
  2123. return rv;
  2124. }
  2125. rv = session_headers_add_pad(session, frame);
  2126. if (rv != 0) {
  2127. return rv;
  2128. }
  2129. assert(session->last_sent_stream_id + 2 <=
  2130. frame->push_promise.promised_stream_id);
  2131. session->last_sent_stream_id = frame->push_promise.promised_stream_id;
  2132. return 0;
  2133. }
  2134. case NGHTTP2_PING:
  2135. if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
  2136. assert(session->obq_flood_counter_ > 0);
  2137. --session->obq_flood_counter_;
  2138. }
  2139. /* PING frame is allowed to be sent unless termination GOAWAY is
  2140. sent */
  2141. if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
  2142. return NGHTTP2_ERR_SESSION_CLOSING;
  2143. }
  2144. nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping);
  2145. return 0;
  2146. case NGHTTP2_GOAWAY:
  2147. rv = nghttp2_frame_pack_goaway(&session->aob.framebufs, &frame->goaway);
  2148. if (rv != 0) {
  2149. return rv;
  2150. }
  2151. session->local_last_stream_id = frame->goaway.last_stream_id;
  2152. return 0;
  2153. case NGHTTP2_WINDOW_UPDATE:
  2154. rv = session_predicate_window_update_send(session, frame->hd.stream_id);
  2155. if (rv != 0) {
  2156. return rv;
  2157. }
  2158. nghttp2_frame_pack_window_update(&session->aob.framebufs,
  2159. &frame->window_update);
  2160. return 0;
  2161. case NGHTTP2_CONTINUATION:
  2162. /* We never handle CONTINUATION here. */
  2163. assert(0);
  2164. return 0;
  2165. default: {
  2166. nghttp2_ext_aux_data *aux_data;
  2167. /* extension frame */
  2168. aux_data = &item->aux_data.ext;
  2169. if (aux_data->builtin == 0) {
  2170. if (session_is_closing(session)) {
  2171. return NGHTTP2_ERR_SESSION_CLOSING;
  2172. }
  2173. return session_pack_extension(session, &session->aob.framebufs, frame);
  2174. }
  2175. switch (frame->hd.type) {
  2176. case NGHTTP2_ALTSVC:
  2177. rv = session_predicate_altsvc_send(session, frame->hd.stream_id);
  2178. if (rv != 0) {
  2179. return rv;
  2180. }
  2181. nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext);
  2182. return 0;
  2183. case NGHTTP2_ORIGIN:
  2184. rv = session_predicate_origin_send(session);
  2185. if (rv != 0) {
  2186. return rv;
  2187. }
  2188. rv = nghttp2_frame_pack_origin(&session->aob.framebufs, &frame->ext);
  2189. if (rv != 0) {
  2190. return rv;
  2191. }
  2192. return 0;
  2193. case NGHTTP2_PRIORITY_UPDATE: {
  2194. nghttp2_ext_priority_update *priority_update = frame->ext.payload;
  2195. rv = session_predicate_priority_update_send(session,
  2196. priority_update->stream_id);
  2197. if (rv != 0) {
  2198. return rv;
  2199. }
  2200. nghttp2_frame_pack_priority_update(&session->aob.framebufs, &frame->ext);
  2201. return 0;
  2202. }
  2203. default:
  2204. /* Unreachable here */
  2205. assert(0);
  2206. return 0;
  2207. }
  2208. }
  2209. }
  2210. }
  2211. nghttp2_outbound_item *
  2212. nghttp2_session_get_next_ob_item(nghttp2_session *session) {
  2213. nghttp2_outbound_item *item;
  2214. if (nghttp2_outbound_queue_top(&session->ob_urgent)) {
  2215. return nghttp2_outbound_queue_top(&session->ob_urgent);
  2216. }
  2217. if (nghttp2_outbound_queue_top(&session->ob_reg)) {
  2218. return nghttp2_outbound_queue_top(&session->ob_reg);
  2219. }
  2220. if (!session_is_outgoing_concurrent_streams_max(session)) {
  2221. if (nghttp2_outbound_queue_top(&session->ob_syn)) {
  2222. return nghttp2_outbound_queue_top(&session->ob_syn);
  2223. }
  2224. }
  2225. if (session->remote_window_size > 0) {
  2226. item = nghttp2_stream_next_outbound_item(&session->root);
  2227. if (item) {
  2228. return item;
  2229. }
  2230. return session_sched_get_next_outbound_item(session);
  2231. }
  2232. return NULL;
  2233. }
  2234. nghttp2_outbound_item *
  2235. nghttp2_session_pop_next_ob_item(nghttp2_session *session) {
  2236. nghttp2_outbound_item *item;
  2237. item = nghttp2_outbound_queue_top(&session->ob_urgent);
  2238. if (item) {
  2239. nghttp2_outbound_queue_pop(&session->ob_urgent);
  2240. item->queued = 0;
  2241. return item;
  2242. }
  2243. item = nghttp2_outbound_queue_top(&session->ob_reg);
  2244. if (item) {
  2245. nghttp2_outbound_queue_pop(&session->ob_reg);
  2246. item->queued = 0;
  2247. return item;
  2248. }
  2249. if (!session_is_outgoing_concurrent_streams_max(session)) {
  2250. item = nghttp2_outbound_queue_top(&session->ob_syn);
  2251. if (item) {
  2252. nghttp2_outbound_queue_pop(&session->ob_syn);
  2253. item->queued = 0;
  2254. return item;
  2255. }
  2256. }
  2257. if (session->remote_window_size > 0) {
  2258. item = nghttp2_stream_next_outbound_item(&session->root);
  2259. if (item) {
  2260. return item;
  2261. }
  2262. return session_sched_get_next_outbound_item(session);
  2263. }
  2264. return NULL;
  2265. }
  2266. static int session_call_before_frame_send(nghttp2_session *session,
  2267. nghttp2_frame *frame) {
  2268. int rv;
  2269. if (session->callbacks.before_frame_send_callback) {
  2270. rv = session->callbacks.before_frame_send_callback(session, frame,
  2271. session->user_data);
  2272. if (rv == NGHTTP2_ERR_CANCEL) {
  2273. return rv;
  2274. }
  2275. if (rv != 0) {
  2276. return NGHTTP2_ERR_CALLBACK_FAILURE;
  2277. }
  2278. }
  2279. return 0;
  2280. }
  2281. static int session_call_on_frame_send(nghttp2_session *session,
  2282. nghttp2_frame *frame) {
  2283. int rv;
  2284. if (session->callbacks.on_frame_send_callback) {
  2285. rv = session->callbacks.on_frame_send_callback(session, frame,
  2286. session->user_data);
  2287. if (rv != 0) {
  2288. return NGHTTP2_ERR_CALLBACK_FAILURE;
  2289. }
  2290. }
  2291. return 0;
  2292. }
  2293. static int find_stream_on_goaway_func(void *entry, void *ptr) {
  2294. nghttp2_close_stream_on_goaway_arg *arg;
  2295. nghttp2_stream *stream;
  2296. arg = (nghttp2_close_stream_on_goaway_arg *)ptr;
  2297. stream = (nghttp2_stream *)entry;
  2298. if (nghttp2_session_is_my_stream_id(arg->session, stream->stream_id)) {
  2299. if (arg->incoming) {
  2300. return 0;
  2301. }
  2302. } else if (!arg->incoming) {
  2303. return 0;
  2304. }
  2305. if (stream->state != NGHTTP2_STREAM_IDLE &&
  2306. (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) == 0 &&
  2307. stream->stream_id > arg->last_stream_id) {
  2308. /* We are collecting streams to close because we cannot call
  2309. nghttp2_session_close_stream() inside nghttp2_map_each().
  2310. Reuse closed_next member.. bad choice? */
  2311. assert(stream->closed_next == NULL);
  2312. assert(stream->closed_prev == NULL);
  2313. if (arg->head) {
  2314. stream->closed_next = arg->head;
  2315. arg->head = stream;
  2316. } else {
  2317. arg->head = stream;
  2318. }
  2319. }
  2320. return 0;
  2321. }
  2322. /* Closes non-idle and non-closed streams whose stream ID >
  2323. last_stream_id. If incoming is nonzero, we are going to close
  2324. incoming streams. Otherwise, close outgoing streams. */
  2325. static int session_close_stream_on_goaway(nghttp2_session *session,
  2326. int32_t last_stream_id,
  2327. int incoming) {
  2328. int rv;
  2329. nghttp2_stream *stream, *next_stream;
  2330. nghttp2_close_stream_on_goaway_arg arg = {session, NULL, last_stream_id,
  2331. incoming};
  2332. rv = nghttp2_map_each(&session->streams, find_stream_on_goaway_func, &arg);
  2333. assert(rv == 0);
  2334. stream = arg.head;
  2335. while (stream) {
  2336. next_stream = stream->closed_next;
  2337. stream->closed_next = NULL;
  2338. rv = nghttp2_session_close_stream(session, stream->stream_id,
  2339. NGHTTP2_REFUSED_STREAM);
  2340. /* stream may be deleted here */
  2341. stream = next_stream;
  2342. if (nghttp2_is_fatal(rv)) {
  2343. /* Clean up closed_next member just in case */
  2344. while (stream) {
  2345. next_stream = stream->closed_next;
  2346. stream->closed_next = NULL;
  2347. stream = next_stream;
  2348. }
  2349. return rv;
  2350. }
  2351. }
  2352. return 0;
  2353. }
  2354. static void session_reschedule_stream(nghttp2_session *session,
  2355. nghttp2_stream *stream) {
  2356. stream->last_writelen = stream->item->frame.hd.length;
  2357. if (!(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES)) {
  2358. nghttp2_stream_reschedule(stream);
  2359. return;
  2360. }
  2361. if (!session->server) {
  2362. return;
  2363. }
  2364. session_sched_reschedule_stream(session, stream);
  2365. }
  2366. static int session_update_stream_consumed_size(nghttp2_session *session,
  2367. nghttp2_stream *stream,
  2368. size_t delta_size);
  2369. static int session_update_connection_consumed_size(nghttp2_session *session,
  2370. size_t delta_size);
  2371. /*
  2372. * Called after a frame is sent. This function runs
  2373. * on_frame_send_callback and handles stream closure upon END_STREAM
  2374. * or RST_STREAM. This function does not reset session->aob. It is a
  2375. * responsibility of session_after_frame_sent2.
  2376. *
  2377. * This function returns 0 if it succeeds, or one of the following
  2378. * negative error codes:
  2379. *
  2380. * NGHTTP2_ERR_NOMEM
  2381. * Out of memory.
  2382. * NGHTTP2_ERR_CALLBACK_FAILURE
  2383. * The callback function failed.
  2384. */
  2385. static int session_after_frame_sent1(nghttp2_session *session) {
  2386. int rv;
  2387. nghttp2_active_outbound_item *aob = &session->aob;
  2388. nghttp2_outbound_item *item = aob->item;
  2389. nghttp2_bufs *framebufs = &aob->framebufs;
  2390. nghttp2_frame *frame;
  2391. nghttp2_stream *stream;
  2392. frame = &item->frame;
  2393. if (frame->hd.type == NGHTTP2_DATA) {
  2394. nghttp2_data_aux_data *aux_data;
  2395. aux_data = &item->aux_data.data;
  2396. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  2397. /* We update flow control window after a frame was completely
  2398. sent. This is possible because we choose payload length not to
  2399. exceed the window */
  2400. session->remote_window_size -= (int32_t)frame->hd.length;
  2401. if (stream) {
  2402. stream->remote_window_size -= (int32_t)frame->hd.length;
  2403. }
  2404. if (stream && aux_data->eof) {
  2405. session_detach_stream_item(session, stream);
  2406. /* Call on_frame_send_callback after
  2407. nghttp2_stream_detach_item(), so that application can issue
  2408. nghttp2_submit_data2() in the callback. */
  2409. if (session->callbacks.on_frame_send_callback) {
  2410. rv = session_call_on_frame_send(session, frame);
  2411. if (nghttp2_is_fatal(rv)) {
  2412. return rv;
  2413. }
  2414. }
  2415. if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
  2416. int stream_closed;
  2417. stream_closed =
  2418. (stream->shut_flags & NGHTTP2_SHUT_RDWR) == NGHTTP2_SHUT_RDWR;
  2419. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
  2420. rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
  2421. if (nghttp2_is_fatal(rv)) {
  2422. return rv;
  2423. }
  2424. /* stream may be NULL if it was closed */
  2425. if (stream_closed) {
  2426. stream = NULL;
  2427. }
  2428. }
  2429. return 0;
  2430. }
  2431. if (session->callbacks.on_frame_send_callback) {
  2432. rv = session_call_on_frame_send(session, frame);
  2433. if (nghttp2_is_fatal(rv)) {
  2434. return rv;
  2435. }
  2436. }
  2437. return 0;
  2438. }
  2439. /* non-DATA frame */
  2440. if (frame->hd.type == NGHTTP2_HEADERS ||
  2441. frame->hd.type == NGHTTP2_PUSH_PROMISE) {
  2442. if (nghttp2_bufs_next_present(framebufs)) {
  2443. DEBUGF("send: CONTINUATION exists, just return\n");
  2444. return 0;
  2445. }
  2446. }
  2447. rv = session_call_on_frame_send(session, frame);
  2448. if (nghttp2_is_fatal(rv)) {
  2449. return rv;
  2450. }
  2451. switch (frame->hd.type) {
  2452. case NGHTTP2_HEADERS: {
  2453. nghttp2_headers_aux_data *aux_data;
  2454. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  2455. if (!stream) {
  2456. return 0;
  2457. }
  2458. switch (frame->headers.cat) {
  2459. case NGHTTP2_HCAT_REQUEST: {
  2460. stream->state = NGHTTP2_STREAM_OPENING;
  2461. if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
  2462. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
  2463. }
  2464. rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
  2465. if (nghttp2_is_fatal(rv)) {
  2466. return rv;
  2467. }
  2468. /* We assume aux_data is a pointer to nghttp2_headers_aux_data */
  2469. aux_data = &item->aux_data.headers;
  2470. if (aux_data->dpw.data_prd.read_callback) {
  2471. /* nghttp2_submit_data_shared() makes a copy of
  2472. aux_data->dpw */
  2473. rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM,
  2474. frame->hd.stream_id, &aux_data->dpw);
  2475. if (nghttp2_is_fatal(rv)) {
  2476. return rv;
  2477. }
  2478. /* TODO nghttp2_submit_data_shared() may fail if stream has
  2479. already DATA frame item. We might have to handle it
  2480. here. */
  2481. }
  2482. return 0;
  2483. }
  2484. case NGHTTP2_HCAT_PUSH_RESPONSE:
  2485. stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH);
  2486. ++session->num_outgoing_streams;
  2487. /* Fall through */
  2488. case NGHTTP2_HCAT_RESPONSE:
  2489. stream->state = NGHTTP2_STREAM_OPENED;
  2490. /* Fall through */
  2491. case NGHTTP2_HCAT_HEADERS:
  2492. if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
  2493. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
  2494. }
  2495. rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
  2496. if (nghttp2_is_fatal(rv)) {
  2497. return rv;
  2498. }
  2499. /* We assume aux_data is a pointer to nghttp2_headers_aux_data */
  2500. aux_data = &item->aux_data.headers;
  2501. if (aux_data->dpw.data_prd.read_callback) {
  2502. rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM,
  2503. frame->hd.stream_id, &aux_data->dpw);
  2504. if (nghttp2_is_fatal(rv)) {
  2505. return rv;
  2506. }
  2507. /* TODO nghttp2_submit_data_shared() may fail if stream has
  2508. already DATA frame item. We might have to handle it
  2509. here. */
  2510. }
  2511. return 0;
  2512. default:
  2513. /* Unreachable */
  2514. assert(0);
  2515. return 0;
  2516. }
  2517. }
  2518. case NGHTTP2_PRIORITY:
  2519. if (session->server || session->pending_no_rfc7540_priorities == 1) {
  2520. return 0;
  2521. }
  2522. stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
  2523. if (!stream) {
  2524. if (!session_detect_idle_stream(session, frame->hd.stream_id)) {
  2525. return 0;
  2526. }
  2527. stream = nghttp2_session_open_stream(
  2528. session, frame->hd.stream_id, NGHTTP2_FLAG_NONE,
  2529. &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL);
  2530. if (!stream) {
  2531. return NGHTTP2_ERR_NOMEM;
  2532. }
  2533. } else {
  2534. rv = nghttp2_session_reprioritize_stream(session, stream,
  2535. &frame->priority.pri_spec);
  2536. if (nghttp2_is_fatal(rv)) {
  2537. return rv;
  2538. }
  2539. }
  2540. rv = nghttp2_session_adjust_idle_stream(session);
  2541. if (nghttp2_is_fatal(rv)) {
  2542. return rv;
  2543. }
  2544. return 0;
  2545. case NGHTTP2_RST_STREAM:
  2546. rv = nghttp2_session_close_stream(session, frame->hd.stream_id,
  2547. frame->rst_stream.error_code);
  2548. if (nghttp2_is_fatal(rv)) {
  2549. return rv;
  2550. }
  2551. return 0;
  2552. case NGHTTP2_GOAWAY: {
  2553. nghttp2_goaway_aux_data *aux_data;
  2554. aux_data = &item->aux_data.goaway;
  2555. if ((aux_data->flags & NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE) == 0) {
  2556. if (aux_data->flags & NGHTTP2_GOAWAY_AUX_TERM_ON_SEND) {
  2557. session->goaway_flags |= NGHTTP2_GOAWAY_TERM_SENT;
  2558. }
  2559. session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
  2560. rv = session_close_stream_on_goaway(session, frame->goaway.last_stream_id,
  2561. 1);
  2562. if (nghttp2_is_fatal(rv)) {
  2563. return rv;
  2564. }
  2565. }
  2566. return 0;
  2567. }
  2568. case NGHTTP2_WINDOW_UPDATE:
  2569. if (frame->hd.stream_id == 0) {
  2570. session->window_update_queued = 0;
  2571. if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
  2572. rv = session_update_connection_consumed_size(session, 0);
  2573. } else {
  2574. rv = nghttp2_session_update_recv_connection_window_size(session, 0);
  2575. }
  2576. if (nghttp2_is_fatal(rv)) {
  2577. return rv;
  2578. }
  2579. return 0;
  2580. }
  2581. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  2582. if (!stream) {
  2583. return 0;
  2584. }
  2585. stream->window_update_queued = 0;
  2586. /* We don't have to send WINDOW_UPDATE if END_STREAM from peer
  2587. is seen. */
  2588. if (stream->shut_flags & NGHTTP2_SHUT_RD) {
  2589. return 0;
  2590. }
  2591. if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
  2592. rv = session_update_stream_consumed_size(session, stream, 0);
  2593. } else {
  2594. rv =
  2595. nghttp2_session_update_recv_stream_window_size(session, stream, 0, 1);
  2596. }
  2597. if (nghttp2_is_fatal(rv)) {
  2598. return rv;
  2599. }
  2600. return 0;
  2601. default:
  2602. return 0;
  2603. }
  2604. }
  2605. /*
  2606. * Called after a frame is sent and session_after_frame_sent1. This
  2607. * function is responsible to reset session->aob.
  2608. */
  2609. static void session_after_frame_sent2(nghttp2_session *session) {
  2610. nghttp2_active_outbound_item *aob = &session->aob;
  2611. nghttp2_outbound_item *item = aob->item;
  2612. nghttp2_bufs *framebufs = &aob->framebufs;
  2613. nghttp2_frame *frame;
  2614. nghttp2_mem *mem;
  2615. nghttp2_stream *stream;
  2616. nghttp2_data_aux_data *aux_data;
  2617. mem = &session->mem;
  2618. frame = &item->frame;
  2619. if (frame->hd.type != NGHTTP2_DATA) {
  2620. if (frame->hd.type == NGHTTP2_HEADERS ||
  2621. frame->hd.type == NGHTTP2_PUSH_PROMISE) {
  2622. if (nghttp2_bufs_next_present(framebufs)) {
  2623. framebufs->cur = framebufs->cur->next;
  2624. DEBUGF("send: next CONTINUATION frame, %zu bytes\n",
  2625. nghttp2_buf_len(&framebufs->cur->buf));
  2626. return;
  2627. }
  2628. }
  2629. active_outbound_item_reset(&session->aob, mem);
  2630. return;
  2631. }
  2632. /* DATA frame */
  2633. aux_data = &item->aux_data.data;
  2634. /* On EOF, we have already detached data. Please note that
  2635. application may issue nghttp2_submit_data2() in
  2636. on_frame_send_callback (call from session_after_frame_sent1),
  2637. which attach data to stream. We don't want to detach it. */
  2638. if (aux_data->eof) {
  2639. active_outbound_item_reset(aob, mem);
  2640. return;
  2641. }
  2642. /* Reset no_copy here because next write may not use this. */
  2643. aux_data->no_copy = 0;
  2644. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  2645. /* If session is closed or RST_STREAM was queued, we won't send
  2646. further data. */
  2647. if (nghttp2_session_predicate_data_send(session, stream) != 0) {
  2648. if (stream) {
  2649. session_detach_stream_item(session, stream);
  2650. }
  2651. active_outbound_item_reset(aob, mem);
  2652. return;
  2653. }
  2654. aob->item = NULL;
  2655. active_outbound_item_reset(&session->aob, mem);
  2656. return;
  2657. }
  2658. static int session_call_send_data(nghttp2_session *session,
  2659. nghttp2_outbound_item *item,
  2660. nghttp2_bufs *framebufs) {
  2661. int rv;
  2662. nghttp2_buf *buf;
  2663. size_t length;
  2664. nghttp2_frame *frame;
  2665. nghttp2_data_aux_data *aux_data;
  2666. buf = &framebufs->cur->buf;
  2667. frame = &item->frame;
  2668. length = frame->hd.length - frame->data.padlen;
  2669. aux_data = &item->aux_data.data;
  2670. rv = session->callbacks.send_data_callback(session, frame, buf->pos, length,
  2671. &aux_data->dpw.data_prd.source,
  2672. session->user_data);
  2673. switch (rv) {
  2674. case 0:
  2675. case NGHTTP2_ERR_WOULDBLOCK:
  2676. case NGHTTP2_ERR_PAUSE:
  2677. case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:
  2678. return rv;
  2679. default:
  2680. return NGHTTP2_ERR_CALLBACK_FAILURE;
  2681. }
  2682. }
  2683. static nghttp2_ssize nghttp2_session_mem_send_internal(nghttp2_session *session,
  2684. const uint8_t **data_ptr,
  2685. int fast_cb) {
  2686. int rv;
  2687. nghttp2_active_outbound_item *aob;
  2688. nghttp2_bufs *framebufs;
  2689. nghttp2_mem *mem;
  2690. mem = &session->mem;
  2691. aob = &session->aob;
  2692. framebufs = &aob->framebufs;
  2693. /* We may have idle streams more than we expect (e.g.,
  2694. nghttp2_session_change_stream_priority() or
  2695. nghttp2_session_create_idle_stream()). Adjust them here. */
  2696. rv = nghttp2_session_adjust_idle_stream(session);
  2697. if (nghttp2_is_fatal(rv)) {
  2698. return rv;
  2699. }
  2700. for (;;) {
  2701. switch (aob->state) {
  2702. case NGHTTP2_OB_POP_ITEM: {
  2703. nghttp2_outbound_item *item;
  2704. item = nghttp2_session_pop_next_ob_item(session);
  2705. if (item == NULL) {
  2706. return 0;
  2707. }
  2708. rv = session_prep_frame(session, item);
  2709. if (rv == NGHTTP2_ERR_PAUSE) {
  2710. return 0;
  2711. }
  2712. if (rv == NGHTTP2_ERR_DEFERRED) {
  2713. DEBUGF("send: frame transmission deferred\n");
  2714. break;
  2715. }
  2716. if (rv < 0) {
  2717. int32_t opened_stream_id = 0;
  2718. uint32_t error_code = NGHTTP2_INTERNAL_ERROR;
  2719. int rv2 = 0;
  2720. DEBUGF("send: frame preparation failed with %s\n",
  2721. nghttp2_strerror(rv));
  2722. /* TODO If the error comes from compressor, the connection
  2723. must be closed. */
  2724. if (item->frame.hd.type != NGHTTP2_DATA &&
  2725. session->callbacks.on_frame_not_send_callback && is_non_fatal(rv)) {
  2726. nghttp2_frame *frame = &item->frame;
  2727. /* The library is responsible for the transmission of
  2728. WINDOW_UPDATE frame, so we don't call error callback for
  2729. it. */
  2730. if (frame->hd.type != NGHTTP2_WINDOW_UPDATE &&
  2731. session->callbacks.on_frame_not_send_callback(
  2732. session, frame, rv, session->user_data) != 0) {
  2733. nghttp2_outbound_item_free(item, mem);
  2734. nghttp2_mem_free(mem, item);
  2735. return NGHTTP2_ERR_CALLBACK_FAILURE;
  2736. }
  2737. }
  2738. /* We have to close stream opened by failed request HEADERS
  2739. or PUSH_PROMISE. */
  2740. switch (item->frame.hd.type) {
  2741. case NGHTTP2_HEADERS:
  2742. if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) {
  2743. opened_stream_id = item->frame.hd.stream_id;
  2744. if (item->aux_data.headers.canceled) {
  2745. error_code = item->aux_data.headers.error_code;
  2746. } else {
  2747. /* Set error_code to REFUSED_STREAM so that application
  2748. can send request again. */
  2749. error_code = NGHTTP2_REFUSED_STREAM;
  2750. }
  2751. }
  2752. break;
  2753. case NGHTTP2_PUSH_PROMISE:
  2754. opened_stream_id = item->frame.push_promise.promised_stream_id;
  2755. break;
  2756. }
  2757. if (opened_stream_id) {
  2758. /* careful not to override rv */
  2759. rv2 =
  2760. nghttp2_session_close_stream(session, opened_stream_id, error_code);
  2761. }
  2762. nghttp2_outbound_item_free(item, mem);
  2763. nghttp2_mem_free(mem, item);
  2764. active_outbound_item_reset(aob, mem);
  2765. if (nghttp2_is_fatal(rv2)) {
  2766. return rv2;
  2767. }
  2768. if (rv == NGHTTP2_ERR_HEADER_COMP) {
  2769. /* If header compression error occurred, should terminate
  2770. connection. */
  2771. rv =
  2772. nghttp2_session_terminate_session(session, NGHTTP2_INTERNAL_ERROR);
  2773. }
  2774. if (nghttp2_is_fatal(rv)) {
  2775. return rv;
  2776. }
  2777. break;
  2778. }
  2779. aob->item = item;
  2780. nghttp2_bufs_rewind(framebufs);
  2781. if (item->frame.hd.type != NGHTTP2_DATA) {
  2782. nghttp2_frame *frame;
  2783. frame = &item->frame;
  2784. DEBUGF("send: next frame: payloadlen=%zu, type=%u, flags=0x%02x, "
  2785. "stream_id=%d\n",
  2786. frame->hd.length, frame->hd.type, frame->hd.flags,
  2787. frame->hd.stream_id);
  2788. rv = session_call_before_frame_send(session, frame);
  2789. if (nghttp2_is_fatal(rv)) {
  2790. return rv;
  2791. }
  2792. if (rv == NGHTTP2_ERR_CANCEL) {
  2793. int32_t opened_stream_id = 0;
  2794. uint32_t error_code = NGHTTP2_INTERNAL_ERROR;
  2795. if (session->callbacks.on_frame_not_send_callback) {
  2796. if (session->callbacks.on_frame_not_send_callback(
  2797. session, frame, rv, session->user_data) != 0) {
  2798. return NGHTTP2_ERR_CALLBACK_FAILURE;
  2799. }
  2800. }
  2801. /* We have to close stream opened by canceled request
  2802. HEADERS or PUSH_PROMISE. */
  2803. switch (item->frame.hd.type) {
  2804. case NGHTTP2_HEADERS:
  2805. if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) {
  2806. opened_stream_id = item->frame.hd.stream_id;
  2807. /* We don't have to check
  2808. item->aux_data.headers.canceled since it has already
  2809. been checked. */
  2810. /* Set error_code to REFUSED_STREAM so that application
  2811. can send request again. */
  2812. error_code = NGHTTP2_REFUSED_STREAM;
  2813. }
  2814. break;
  2815. case NGHTTP2_PUSH_PROMISE:
  2816. opened_stream_id = item->frame.push_promise.promised_stream_id;
  2817. break;
  2818. }
  2819. if (opened_stream_id) {
  2820. /* careful not to override rv */
  2821. int rv2;
  2822. rv2 = nghttp2_session_close_stream(session, opened_stream_id,
  2823. error_code);
  2824. if (nghttp2_is_fatal(rv2)) {
  2825. return rv2;
  2826. }
  2827. }
  2828. active_outbound_item_reset(aob, mem);
  2829. break;
  2830. }
  2831. } else {
  2832. DEBUGF("send: next frame: DATA\n");
  2833. if (item->aux_data.data.no_copy) {
  2834. aob->state = NGHTTP2_OB_SEND_NO_COPY;
  2835. break;
  2836. }
  2837. }
  2838. DEBUGF("send: start transmitting frame type=%u, length=%td\n",
  2839. framebufs->cur->buf.pos[3],
  2840. framebufs->cur->buf.last - framebufs->cur->buf.pos);
  2841. aob->state = NGHTTP2_OB_SEND_DATA;
  2842. break;
  2843. }
  2844. case NGHTTP2_OB_SEND_DATA: {
  2845. size_t datalen;
  2846. nghttp2_buf *buf;
  2847. buf = &framebufs->cur->buf;
  2848. if (buf->pos == buf->last) {
  2849. DEBUGF("send: end transmission of a frame\n");
  2850. /* Frame has completely sent */
  2851. if (fast_cb) {
  2852. session_after_frame_sent2(session);
  2853. } else {
  2854. rv = session_after_frame_sent1(session);
  2855. if (rv < 0) {
  2856. /* FATAL */
  2857. assert(nghttp2_is_fatal(rv));
  2858. return rv;
  2859. }
  2860. session_after_frame_sent2(session);
  2861. }
  2862. /* We have already adjusted the next state */
  2863. break;
  2864. }
  2865. *data_ptr = buf->pos;
  2866. datalen = nghttp2_buf_len(buf);
  2867. /* We increment the offset here. If send_callback does not send
  2868. everything, we will adjust it. */
  2869. buf->pos += datalen;
  2870. return (nghttp2_ssize)datalen;
  2871. }
  2872. case NGHTTP2_OB_SEND_NO_COPY: {
  2873. nghttp2_stream *stream;
  2874. nghttp2_frame *frame;
  2875. int pause;
  2876. DEBUGF("send: no copy DATA\n");
  2877. frame = &aob->item->frame;
  2878. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  2879. if (stream == NULL) {
  2880. DEBUGF("send: no copy DATA cancelled because stream was closed\n");
  2881. active_outbound_item_reset(aob, mem);
  2882. break;
  2883. }
  2884. rv = session_call_send_data(session, aob->item, framebufs);
  2885. if (nghttp2_is_fatal(rv)) {
  2886. return rv;
  2887. }
  2888. if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  2889. session_detach_stream_item(session, stream);
  2890. rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id,
  2891. NGHTTP2_INTERNAL_ERROR);
  2892. if (nghttp2_is_fatal(rv)) {
  2893. return rv;
  2894. }
  2895. active_outbound_item_reset(aob, mem);
  2896. break;
  2897. }
  2898. if (rv == NGHTTP2_ERR_WOULDBLOCK) {
  2899. return 0;
  2900. }
  2901. pause = (rv == NGHTTP2_ERR_PAUSE);
  2902. rv = session_after_frame_sent1(session);
  2903. if (rv < 0) {
  2904. assert(nghttp2_is_fatal(rv));
  2905. return rv;
  2906. }
  2907. session_after_frame_sent2(session);
  2908. /* We have already adjusted the next state */
  2909. if (pause) {
  2910. return 0;
  2911. }
  2912. break;
  2913. }
  2914. case NGHTTP2_OB_SEND_CLIENT_MAGIC: {
  2915. size_t datalen;
  2916. nghttp2_buf *buf;
  2917. buf = &framebufs->cur->buf;
  2918. if (buf->pos == buf->last) {
  2919. DEBUGF("send: end transmission of client magic\n");
  2920. active_outbound_item_reset(aob, mem);
  2921. break;
  2922. }
  2923. *data_ptr = buf->pos;
  2924. datalen = nghttp2_buf_len(buf);
  2925. buf->pos += datalen;
  2926. return (nghttp2_ssize)datalen;
  2927. }
  2928. }
  2929. }
  2930. }
  2931. ssize_t nghttp2_session_mem_send(nghttp2_session *session,
  2932. const uint8_t **data_ptr) {
  2933. return (ssize_t)nghttp2_session_mem_send2(session, data_ptr);
  2934. }
  2935. nghttp2_ssize nghttp2_session_mem_send2(nghttp2_session *session,
  2936. const uint8_t **data_ptr) {
  2937. int rv;
  2938. nghttp2_ssize len;
  2939. *data_ptr = NULL;
  2940. len = nghttp2_session_mem_send_internal(session, data_ptr, 1);
  2941. if (len <= 0) {
  2942. return len;
  2943. }
  2944. if (session->aob.item) {
  2945. /* We have to call session_after_frame_sent1 here to handle stream
  2946. closure upon transmission of frames. Otherwise, END_STREAM may
  2947. be reached to client before we call nghttp2_session_mem_send
  2948. again and we may get exceeding number of incoming streams. */
  2949. rv = session_after_frame_sent1(session);
  2950. if (rv < 0) {
  2951. assert(nghttp2_is_fatal(rv));
  2952. return (nghttp2_ssize)rv;
  2953. }
  2954. }
  2955. return len;
  2956. }
  2957. int nghttp2_session_send(nghttp2_session *session) {
  2958. const uint8_t *data = NULL;
  2959. nghttp2_ssize datalen;
  2960. nghttp2_ssize sentlen;
  2961. nghttp2_bufs *framebufs;
  2962. framebufs = &session->aob.framebufs;
  2963. for (;;) {
  2964. datalen = nghttp2_session_mem_send_internal(session, &data, 0);
  2965. if (datalen <= 0) {
  2966. return (int)datalen;
  2967. }
  2968. if (session->callbacks.send_callback2) {
  2969. sentlen = session->callbacks.send_callback2(
  2970. session, data, (size_t)datalen, 0, session->user_data);
  2971. } else {
  2972. sentlen = (nghttp2_ssize)session->callbacks.send_callback(
  2973. session, data, (size_t)datalen, 0, session->user_data);
  2974. }
  2975. if (sentlen < 0) {
  2976. if (sentlen == NGHTTP2_ERR_WOULDBLOCK) {
  2977. /* Transmission canceled. Rewind the offset */
  2978. framebufs->cur->buf.pos -= datalen;
  2979. return 0;
  2980. }
  2981. return NGHTTP2_ERR_CALLBACK_FAILURE;
  2982. }
  2983. /* Rewind the offset to the amount of unsent bytes */
  2984. framebufs->cur->buf.pos -= datalen - sentlen;
  2985. }
  2986. }
  2987. static nghttp2_ssize session_recv(nghttp2_session *session, uint8_t *buf,
  2988. size_t len) {
  2989. nghttp2_ssize rv;
  2990. if (session->callbacks.recv_callback2) {
  2991. rv = session->callbacks.recv_callback2(session, buf, len, 0,
  2992. session->user_data);
  2993. } else {
  2994. rv = (nghttp2_ssize)session->callbacks.recv_callback(session, buf, len, 0,
  2995. session->user_data);
  2996. }
  2997. if (rv > 0) {
  2998. if ((size_t)rv > len) {
  2999. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3000. }
  3001. } else if (rv < 0 && rv != NGHTTP2_ERR_WOULDBLOCK && rv != NGHTTP2_ERR_EOF) {
  3002. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3003. }
  3004. return rv;
  3005. }
  3006. static int session_call_on_begin_frame(nghttp2_session *session,
  3007. const nghttp2_frame_hd *hd) {
  3008. int rv;
  3009. if (session->callbacks.on_begin_frame_callback) {
  3010. rv = session->callbacks.on_begin_frame_callback(session, hd,
  3011. session->user_data);
  3012. if (rv != 0) {
  3013. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3014. }
  3015. }
  3016. return 0;
  3017. }
  3018. static int session_call_on_frame_received(nghttp2_session *session,
  3019. nghttp2_frame *frame) {
  3020. int rv;
  3021. if (session->callbacks.on_frame_recv_callback) {
  3022. rv = session->callbacks.on_frame_recv_callback(session, frame,
  3023. session->user_data);
  3024. if (rv != 0) {
  3025. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3026. }
  3027. }
  3028. return 0;
  3029. }
  3030. static int session_call_on_begin_headers(nghttp2_session *session,
  3031. nghttp2_frame *frame) {
  3032. int rv;
  3033. DEBUGF("recv: call on_begin_headers callback stream_id=%d\n",
  3034. frame->hd.stream_id);
  3035. if (session->callbacks.on_begin_headers_callback) {
  3036. rv = session->callbacks.on_begin_headers_callback(session, frame,
  3037. session->user_data);
  3038. if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  3039. return rv;
  3040. }
  3041. if (rv != 0) {
  3042. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3043. }
  3044. }
  3045. return 0;
  3046. }
  3047. static int session_call_on_header(nghttp2_session *session,
  3048. const nghttp2_frame *frame,
  3049. const nghttp2_hd_nv *nv) {
  3050. int rv = 0;
  3051. if (session->callbacks.on_header_callback2) {
  3052. rv = session->callbacks.on_header_callback2(
  3053. session, frame, nv->name, nv->value, nv->flags, session->user_data);
  3054. } else if (session->callbacks.on_header_callback) {
  3055. rv = session->callbacks.on_header_callback(
  3056. session, frame, nv->name->base, nv->name->len, nv->value->base,
  3057. nv->value->len, nv->flags, session->user_data);
  3058. }
  3059. if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  3060. return rv;
  3061. }
  3062. if (rv != 0) {
  3063. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3064. }
  3065. return 0;
  3066. }
  3067. static int session_call_on_invalid_header(nghttp2_session *session,
  3068. const nghttp2_frame *frame,
  3069. const nghttp2_hd_nv *nv) {
  3070. int rv;
  3071. if (session->callbacks.on_invalid_header_callback2) {
  3072. rv = session->callbacks.on_invalid_header_callback2(
  3073. session, frame, nv->name, nv->value, nv->flags, session->user_data);
  3074. } else if (session->callbacks.on_invalid_header_callback) {
  3075. rv = session->callbacks.on_invalid_header_callback(
  3076. session, frame, nv->name->base, nv->name->len, nv->value->base,
  3077. nv->value->len, nv->flags, session->user_data);
  3078. } else {
  3079. return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
  3080. }
  3081. if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  3082. return rv;
  3083. }
  3084. if (rv != 0) {
  3085. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3086. }
  3087. return 0;
  3088. }
  3089. static int
  3090. session_call_on_extension_chunk_recv_callback(nghttp2_session *session,
  3091. const uint8_t *data, size_t len) {
  3092. int rv;
  3093. nghttp2_inbound_frame *iframe = &session->iframe;
  3094. nghttp2_frame *frame = &iframe->frame;
  3095. if (session->callbacks.on_extension_chunk_recv_callback) {
  3096. rv = session->callbacks.on_extension_chunk_recv_callback(
  3097. session, &frame->hd, data, len, session->user_data);
  3098. if (rv == NGHTTP2_ERR_CANCEL) {
  3099. return rv;
  3100. }
  3101. if (rv != 0) {
  3102. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3103. }
  3104. }
  3105. return 0;
  3106. }
  3107. static int session_call_unpack_extension_callback(nghttp2_session *session) {
  3108. int rv;
  3109. nghttp2_inbound_frame *iframe = &session->iframe;
  3110. nghttp2_frame *frame = &iframe->frame;
  3111. void *payload = NULL;
  3112. rv = session->callbacks.unpack_extension_callback(
  3113. session, &payload, &frame->hd, session->user_data);
  3114. if (rv == NGHTTP2_ERR_CANCEL) {
  3115. return rv;
  3116. }
  3117. if (rv != 0) {
  3118. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3119. }
  3120. frame->ext.payload = payload;
  3121. return 0;
  3122. }
  3123. /*
  3124. * Handles frame size error.
  3125. *
  3126. * This function returns 0 if it succeeds, or one of the following
  3127. * negative error codes:
  3128. *
  3129. * NGHTTP2_ERR_NOMEM
  3130. * Out of memory.
  3131. */
  3132. static int session_handle_frame_size_error(nghttp2_session *session) {
  3133. /* TODO Currently no callback is called for this error, because we
  3134. call this callback before reading any payload */
  3135. return nghttp2_session_terminate_session(session, NGHTTP2_FRAME_SIZE_ERROR);
  3136. }
  3137. static uint32_t get_error_code_from_lib_error_code(int lib_error_code) {
  3138. switch (lib_error_code) {
  3139. case NGHTTP2_ERR_STREAM_CLOSED:
  3140. return NGHTTP2_STREAM_CLOSED;
  3141. case NGHTTP2_ERR_HEADER_COMP:
  3142. return NGHTTP2_COMPRESSION_ERROR;
  3143. case NGHTTP2_ERR_FRAME_SIZE_ERROR:
  3144. return NGHTTP2_FRAME_SIZE_ERROR;
  3145. case NGHTTP2_ERR_FLOW_CONTROL:
  3146. return NGHTTP2_FLOW_CONTROL_ERROR;
  3147. case NGHTTP2_ERR_REFUSED_STREAM:
  3148. return NGHTTP2_REFUSED_STREAM;
  3149. case NGHTTP2_ERR_PROTO:
  3150. case NGHTTP2_ERR_HTTP_HEADER:
  3151. case NGHTTP2_ERR_HTTP_MESSAGING:
  3152. return NGHTTP2_PROTOCOL_ERROR;
  3153. default:
  3154. return NGHTTP2_INTERNAL_ERROR;
  3155. }
  3156. }
  3157. /*
  3158. * Calls on_invalid_frame_recv_callback if it is set to |session|.
  3159. *
  3160. * This function returns 0 if it succeeds, or one of the following
  3161. * negative error codes:
  3162. *
  3163. * NGHTTP2_ERR_CALLBACK_FAILURE
  3164. * User defined callback function fails.
  3165. */
  3166. static int session_call_on_invalid_frame_recv_callback(nghttp2_session *session,
  3167. nghttp2_frame *frame,
  3168. int lib_error_code) {
  3169. if (session->callbacks.on_invalid_frame_recv_callback) {
  3170. if (session->callbacks.on_invalid_frame_recv_callback(
  3171. session, frame, lib_error_code, session->user_data) != 0) {
  3172. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3173. }
  3174. }
  3175. return 0;
  3176. }
  3177. static int session_handle_invalid_stream2(nghttp2_session *session,
  3178. int32_t stream_id,
  3179. nghttp2_frame *frame,
  3180. int lib_error_code) {
  3181. int rv;
  3182. rv = nghttp2_session_add_rst_stream(
  3183. session, stream_id, get_error_code_from_lib_error_code(lib_error_code));
  3184. if (rv != 0) {
  3185. return rv;
  3186. }
  3187. if (session->callbacks.on_invalid_frame_recv_callback) {
  3188. if (session->callbacks.on_invalid_frame_recv_callback(
  3189. session, frame, lib_error_code, session->user_data) != 0) {
  3190. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3191. }
  3192. }
  3193. return 0;
  3194. }
  3195. static int session_handle_invalid_stream(nghttp2_session *session,
  3196. nghttp2_frame *frame,
  3197. int lib_error_code) {
  3198. return session_handle_invalid_stream2(session, frame->hd.stream_id, frame,
  3199. lib_error_code);
  3200. }
  3201. static int session_inflate_handle_invalid_stream(nghttp2_session *session,
  3202. nghttp2_frame *frame,
  3203. int lib_error_code) {
  3204. int rv;
  3205. rv = session_handle_invalid_stream(session, frame, lib_error_code);
  3206. if (nghttp2_is_fatal(rv)) {
  3207. return rv;
  3208. }
  3209. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3210. }
  3211. /*
  3212. * Handles invalid frame which causes connection error.
  3213. */
  3214. static int session_handle_invalid_connection(nghttp2_session *session,
  3215. nghttp2_frame *frame,
  3216. int lib_error_code,
  3217. const char *reason) {
  3218. if (session->callbacks.on_invalid_frame_recv_callback) {
  3219. if (session->callbacks.on_invalid_frame_recv_callback(
  3220. session, frame, lib_error_code, session->user_data) != 0) {
  3221. return NGHTTP2_ERR_CALLBACK_FAILURE;
  3222. }
  3223. }
  3224. return nghttp2_session_terminate_session_with_reason(
  3225. session, get_error_code_from_lib_error_code(lib_error_code), reason);
  3226. }
  3227. static int session_inflate_handle_invalid_connection(nghttp2_session *session,
  3228. nghttp2_frame *frame,
  3229. int lib_error_code,
  3230. const char *reason) {
  3231. int rv;
  3232. rv =
  3233. session_handle_invalid_connection(session, frame, lib_error_code, reason);
  3234. if (nghttp2_is_fatal(rv)) {
  3235. return rv;
  3236. }
  3237. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3238. }
  3239. /*
  3240. * Inflates header block in the memory pointed by |in| with |inlen|
  3241. * bytes. If this function returns NGHTTP2_ERR_PAUSE, the caller must
  3242. * call this function again, until it returns 0 or one of negative
  3243. * error code. If |call_header_cb| is zero, the on_header_callback
  3244. * are not invoked and the function never return NGHTTP2_ERR_PAUSE. If
  3245. * the given |in| is the last chunk of header block, the |final| must
  3246. * be nonzero. If header block is successfully processed (which is
  3247. * indicated by the return value 0, NGHTTP2_ERR_PAUSE or
  3248. * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE), the number of processed
  3249. * input bytes is assigned to the |*readlen_ptr|.
  3250. *
  3251. * This function return 0 if it succeeds, or one of the negative error
  3252. * codes:
  3253. *
  3254. * NGHTTP2_ERR_CALLBACK_FAILURE
  3255. * The callback function failed.
  3256. * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
  3257. * The callback returns this error code, indicating that this
  3258. * stream should be RST_STREAMed.
  3259. * NGHTTP2_ERR_NOMEM
  3260. * Out of memory.
  3261. * NGHTTP2_ERR_PAUSE
  3262. * The callback function returned NGHTTP2_ERR_PAUSE
  3263. * NGHTTP2_ERR_HEADER_COMP
  3264. * Header decompression failed
  3265. */
  3266. static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
  3267. size_t *readlen_ptr, uint8_t *in, size_t inlen,
  3268. int final, int call_header_cb) {
  3269. nghttp2_ssize proclen;
  3270. int rv;
  3271. int inflate_flags;
  3272. nghttp2_hd_nv nv;
  3273. nghttp2_stream *stream;
  3274. nghttp2_stream *subject_stream;
  3275. int trailer = 0;
  3276. *readlen_ptr = 0;
  3277. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  3278. if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
  3279. subject_stream = nghttp2_session_get_stream(
  3280. session, frame->push_promise.promised_stream_id);
  3281. } else {
  3282. subject_stream = stream;
  3283. trailer = session_trailer_headers(session, stream, frame);
  3284. }
  3285. DEBUGF("recv: decoding header block %zu bytes\n", inlen);
  3286. for (;;) {
  3287. inflate_flags = 0;
  3288. proclen = nghttp2_hd_inflate_hd_nv(&session->hd_inflater, &nv,
  3289. &inflate_flags, in, inlen, final);
  3290. if (nghttp2_is_fatal((int)proclen)) {
  3291. return (int)proclen;
  3292. }
  3293. if (proclen < 0) {
  3294. if (session->iframe.state == NGHTTP2_IB_READ_HEADER_BLOCK) {
  3295. if (subject_stream && subject_stream->state != NGHTTP2_STREAM_CLOSING) {
  3296. /* Adding RST_STREAM here is very important. It prevents
  3297. from invoking subsequent callbacks for the same stream
  3298. ID. */
  3299. rv = nghttp2_session_add_rst_stream(
  3300. session, subject_stream->stream_id, NGHTTP2_COMPRESSION_ERROR);
  3301. if (nghttp2_is_fatal(rv)) {
  3302. return rv;
  3303. }
  3304. }
  3305. }
  3306. rv =
  3307. nghttp2_session_terminate_session(session, NGHTTP2_COMPRESSION_ERROR);
  3308. if (nghttp2_is_fatal(rv)) {
  3309. return rv;
  3310. }
  3311. return NGHTTP2_ERR_HEADER_COMP;
  3312. }
  3313. in += proclen;
  3314. inlen -= (size_t)proclen;
  3315. *readlen_ptr += (size_t)proclen;
  3316. DEBUGF("recv: proclen=%td\n", proclen);
  3317. if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
  3318. rv = 0;
  3319. if (subject_stream) {
  3320. if (session_enforce_http_messaging(session)) {
  3321. rv = nghttp2_http_on_header(session, subject_stream, frame, &nv,
  3322. trailer);
  3323. if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
  3324. /* Don't overwrite rv here */
  3325. int rv2;
  3326. rv2 = session_call_on_invalid_header(session, frame, &nv);
  3327. if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  3328. rv = NGHTTP2_ERR_HTTP_HEADER;
  3329. } else {
  3330. if (rv2 != 0) {
  3331. return rv2;
  3332. }
  3333. /* header is ignored */
  3334. DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
  3335. frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
  3336. nv.name->base, (int)nv.value->len, nv.value->base);
  3337. rv2 = session_call_error_callback(
  3338. session, NGHTTP2_ERR_HTTP_HEADER,
  3339. "Ignoring received invalid HTTP header field: frame type: "
  3340. "%u, stream: %d, name: [%.*s], value: [%.*s]",
  3341. frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
  3342. nv.name->base, (int)nv.value->len, nv.value->base);
  3343. if (nghttp2_is_fatal(rv2)) {
  3344. return rv2;
  3345. }
  3346. }
  3347. }
  3348. if (rv == NGHTTP2_ERR_HTTP_HEADER) {
  3349. DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
  3350. frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
  3351. nv.name->base, (int)nv.value->len, nv.value->base);
  3352. rv = session_call_error_callback(
  3353. session, NGHTTP2_ERR_HTTP_HEADER,
  3354. "Invalid HTTP header field was received: frame type: "
  3355. "%u, stream: %d, name: [%.*s], value: [%.*s]",
  3356. frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
  3357. nv.name->base, (int)nv.value->len, nv.value->base);
  3358. if (nghttp2_is_fatal(rv)) {
  3359. return rv;
  3360. }
  3361. rv =
  3362. session_handle_invalid_stream2(session, subject_stream->stream_id,
  3363. frame, NGHTTP2_ERR_HTTP_HEADER);
  3364. if (nghttp2_is_fatal(rv)) {
  3365. return rv;
  3366. }
  3367. return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
  3368. }
  3369. }
  3370. if (rv == 0) {
  3371. rv = session_call_on_header(session, frame, &nv);
  3372. /* This handles NGHTTP2_ERR_PAUSE and
  3373. NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
  3374. if (rv != 0) {
  3375. return rv;
  3376. }
  3377. }
  3378. }
  3379. }
  3380. if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
  3381. nghttp2_hd_inflate_end_headers(&session->hd_inflater);
  3382. break;
  3383. }
  3384. if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) {
  3385. break;
  3386. }
  3387. }
  3388. return 0;
  3389. }
  3390. /*
  3391. * Call this function when HEADERS frame was completely received.
  3392. *
  3393. * This function returns 0 if it succeeds, or one of negative error
  3394. * codes:
  3395. *
  3396. * NGHTTP2_ERR_CALLBACK_FAILURE
  3397. * The callback function failed.
  3398. * NGHTTP2_ERR_NOMEM
  3399. * Out of memory.
  3400. */
  3401. static int session_end_stream_headers_received(nghttp2_session *session,
  3402. nghttp2_frame *frame,
  3403. nghttp2_stream *stream) {
  3404. int rv;
  3405. assert(frame->hd.type == NGHTTP2_HEADERS);
  3406. if (session->server && session_enforce_http_messaging(session) &&
  3407. frame->headers.cat == NGHTTP2_HCAT_REQUEST &&
  3408. (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) &&
  3409. !(stream->flags & NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES) &&
  3410. (stream->http_flags & NGHTTP2_HTTP_FLAG_PRIORITY)) {
  3411. rv = session_update_stream_priority(session, stream, stream->http_extpri);
  3412. if (rv != 0) {
  3413. assert(nghttp2_is_fatal(rv));
  3414. return rv;
  3415. }
  3416. }
  3417. if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
  3418. return 0;
  3419. }
  3420. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
  3421. rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
  3422. if (nghttp2_is_fatal(rv)) {
  3423. return rv;
  3424. }
  3425. return 0;
  3426. }
  3427. static int session_after_header_block_received(nghttp2_session *session) {
  3428. int rv = 0;
  3429. nghttp2_frame *frame = &session->iframe.frame;
  3430. nghttp2_stream *stream;
  3431. /* We don't call on_frame_recv_callback if stream has been closed
  3432. already or being closed. */
  3433. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  3434. if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) {
  3435. return 0;
  3436. }
  3437. if (session_enforce_http_messaging(session)) {
  3438. if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
  3439. nghttp2_stream *subject_stream;
  3440. subject_stream = nghttp2_session_get_stream(
  3441. session, frame->push_promise.promised_stream_id);
  3442. if (subject_stream) {
  3443. rv = nghttp2_http_on_request_headers(subject_stream, frame);
  3444. }
  3445. } else {
  3446. assert(frame->hd.type == NGHTTP2_HEADERS);
  3447. switch (frame->headers.cat) {
  3448. case NGHTTP2_HCAT_REQUEST:
  3449. rv = nghttp2_http_on_request_headers(stream, frame);
  3450. break;
  3451. case NGHTTP2_HCAT_RESPONSE:
  3452. case NGHTTP2_HCAT_PUSH_RESPONSE:
  3453. rv = nghttp2_http_on_response_headers(stream);
  3454. break;
  3455. case NGHTTP2_HCAT_HEADERS:
  3456. if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) {
  3457. assert(!session->server);
  3458. rv = nghttp2_http_on_response_headers(stream);
  3459. } else {
  3460. rv = nghttp2_http_on_trailer_headers(stream, frame);
  3461. }
  3462. break;
  3463. default:
  3464. assert(0);
  3465. }
  3466. if (rv == 0 && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
  3467. rv = nghttp2_http_on_remote_end_stream(stream);
  3468. }
  3469. }
  3470. if (rv != 0) {
  3471. int32_t stream_id;
  3472. if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
  3473. stream_id = frame->push_promise.promised_stream_id;
  3474. } else {
  3475. stream_id = frame->hd.stream_id;
  3476. }
  3477. rv = session_handle_invalid_stream2(session, stream_id, frame,
  3478. NGHTTP2_ERR_HTTP_MESSAGING);
  3479. if (nghttp2_is_fatal(rv)) {
  3480. return rv;
  3481. }
  3482. if (frame->hd.type == NGHTTP2_HEADERS &&
  3483. (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
  3484. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
  3485. /* Don't call nghttp2_session_close_stream_if_shut_rdwr
  3486. because RST_STREAM has been submitted. */
  3487. }
  3488. return 0;
  3489. }
  3490. }
  3491. rv = session_call_on_frame_received(session, frame);
  3492. if (nghttp2_is_fatal(rv)) {
  3493. return rv;
  3494. }
  3495. if (frame->hd.type != NGHTTP2_HEADERS) {
  3496. return 0;
  3497. }
  3498. return session_end_stream_headers_received(session, frame, stream);
  3499. }
  3500. int nghttp2_session_on_request_headers_received(nghttp2_session *session,
  3501. nghttp2_frame *frame) {
  3502. int rv = 0;
  3503. nghttp2_stream *stream;
  3504. if (frame->hd.stream_id == 0) {
  3505. return session_inflate_handle_invalid_connection(
  3506. session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: stream_id == 0");
  3507. }
  3508. /* If client receives idle stream from server, it is invalid
  3509. regardless stream ID is even or odd. This is because client is
  3510. not expected to receive request from server. */
  3511. if (!session->server) {
  3512. if (session_detect_idle_stream(session, frame->hd.stream_id)) {
  3513. return session_inflate_handle_invalid_connection(
  3514. session, frame, NGHTTP2_ERR_PROTO,
  3515. "request HEADERS: client received request");
  3516. }
  3517. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3518. }
  3519. assert(session->server);
  3520. if (!session_is_new_peer_stream_id(session, frame->hd.stream_id)) {
  3521. if (frame->hd.stream_id == 0 ||
  3522. nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
  3523. return session_inflate_handle_invalid_connection(
  3524. session, frame, NGHTTP2_ERR_PROTO,
  3525. "request HEADERS: invalid stream_id");
  3526. }
  3527. /* RFC 7540 says if an endpoint receives a HEADERS with invalid
  3528. * stream ID (e.g, numerically smaller than previous), it MUST
  3529. * issue connection error with error code PROTOCOL_ERROR. It is a
  3530. * bit hard to detect this, since we cannot remember all streams
  3531. * we observed so far.
  3532. *
  3533. * You might imagine this is really easy. But no. HTTP/2 is
  3534. * asynchronous protocol, and usually client and server do not
  3535. * share the complete picture of open/closed stream status. For
  3536. * example, after server sends RST_STREAM for a stream, client may
  3537. * send trailer HEADERS for that stream. If naive server detects
  3538. * that, and issued connection error, then it is a bug of server
  3539. * implementation since client is not wrong if it did not get
  3540. * RST_STREAM when it issued trailer HEADERS.
  3541. *
  3542. * At the moment, we are very conservative here. We only use
  3543. * connection error if stream ID refers idle stream, or we are
  3544. * sure that stream is half-closed(remote) or closed. Otherwise
  3545. * we just ignore HEADERS for now.
  3546. */
  3547. stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
  3548. if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) {
  3549. return session_inflate_handle_invalid_connection(
  3550. session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed");
  3551. }
  3552. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3553. }
  3554. session->last_recv_stream_id = frame->hd.stream_id;
  3555. if (session_is_incoming_concurrent_streams_max(session)) {
  3556. return session_inflate_handle_invalid_connection(
  3557. session, frame, NGHTTP2_ERR_PROTO,
  3558. "request HEADERS: max concurrent streams exceeded");
  3559. }
  3560. if (!session_allow_incoming_new_stream(session)) {
  3561. /* We just ignore stream after GOAWAY was sent */
  3562. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3563. }
  3564. if (frame->headers.pri_spec.stream_id == frame->hd.stream_id) {
  3565. return session_inflate_handle_invalid_connection(
  3566. session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: depend on itself");
  3567. }
  3568. if (session_is_incoming_concurrent_streams_pending_max(session)) {
  3569. return session_inflate_handle_invalid_stream(session, frame,
  3570. NGHTTP2_ERR_REFUSED_STREAM);
  3571. }
  3572. stream = nghttp2_session_open_stream(
  3573. session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE,
  3574. &frame->headers.pri_spec, NGHTTP2_STREAM_OPENING, NULL);
  3575. if (!stream) {
  3576. return NGHTTP2_ERR_NOMEM;
  3577. }
  3578. rv = nghttp2_session_adjust_closed_stream(session);
  3579. if (nghttp2_is_fatal(rv)) {
  3580. return rv;
  3581. }
  3582. session->last_proc_stream_id = session->last_recv_stream_id;
  3583. rv = session_call_on_begin_headers(session, frame);
  3584. if (rv != 0) {
  3585. return rv;
  3586. }
  3587. return 0;
  3588. }
  3589. int nghttp2_session_on_response_headers_received(nghttp2_session *session,
  3590. nghttp2_frame *frame,
  3591. nghttp2_stream *stream) {
  3592. int rv;
  3593. /* This function is only called if stream->state ==
  3594. NGHTTP2_STREAM_OPENING and stream_id is local side initiated. */
  3595. assert(stream->state == NGHTTP2_STREAM_OPENING &&
  3596. nghttp2_session_is_my_stream_id(session, frame->hd.stream_id));
  3597. if (frame->hd.stream_id == 0) {
  3598. return session_inflate_handle_invalid_connection(
  3599. session, frame, NGHTTP2_ERR_PROTO, "response HEADERS: stream_id == 0");
  3600. }
  3601. if (stream->shut_flags & NGHTTP2_SHUT_RD) {
  3602. /* half closed (remote): from the spec:
  3603. If an endpoint receives additional frames for a stream that is
  3604. in this state it MUST respond with a stream error (Section
  3605. 5.4.2) of type STREAM_CLOSED.
  3606. We go further, and make it connection error.
  3607. */
  3608. return session_inflate_handle_invalid_connection(
  3609. session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed");
  3610. }
  3611. stream->state = NGHTTP2_STREAM_OPENED;
  3612. rv = session_call_on_begin_headers(session, frame);
  3613. if (rv != 0) {
  3614. return rv;
  3615. }
  3616. return 0;
  3617. }
  3618. int nghttp2_session_on_push_response_headers_received(nghttp2_session *session,
  3619. nghttp2_frame *frame,
  3620. nghttp2_stream *stream) {
  3621. int rv = 0;
  3622. assert(stream->state == NGHTTP2_STREAM_RESERVED);
  3623. if (frame->hd.stream_id == 0) {
  3624. return session_inflate_handle_invalid_connection(
  3625. session, frame, NGHTTP2_ERR_PROTO,
  3626. "push response HEADERS: stream_id == 0");
  3627. }
  3628. if (session->server) {
  3629. return session_inflate_handle_invalid_connection(
  3630. session, frame, NGHTTP2_ERR_PROTO,
  3631. "HEADERS: no HEADERS allowed from client in reserved state");
  3632. }
  3633. if (session_is_incoming_concurrent_streams_max(session)) {
  3634. return session_inflate_handle_invalid_connection(
  3635. session, frame, NGHTTP2_ERR_PROTO,
  3636. "push response HEADERS: max concurrent streams exceeded");
  3637. }
  3638. if (!session_allow_incoming_new_stream(session)) {
  3639. /* We don't accept new stream after GOAWAY was sent. */
  3640. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3641. }
  3642. if (session_is_incoming_concurrent_streams_pending_max(session)) {
  3643. return session_inflate_handle_invalid_stream(session, frame,
  3644. NGHTTP2_ERR_REFUSED_STREAM);
  3645. }
  3646. nghttp2_stream_promise_fulfilled(stream);
  3647. if (!nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
  3648. --session->num_incoming_reserved_streams;
  3649. }
  3650. ++session->num_incoming_streams;
  3651. rv = session_call_on_begin_headers(session, frame);
  3652. if (rv != 0) {
  3653. return rv;
  3654. }
  3655. return 0;
  3656. }
  3657. int nghttp2_session_on_headers_received(nghttp2_session *session,
  3658. nghttp2_frame *frame,
  3659. nghttp2_stream *stream) {
  3660. int rv = 0;
  3661. if (frame->hd.stream_id == 0) {
  3662. return session_inflate_handle_invalid_connection(
  3663. session, frame, NGHTTP2_ERR_PROTO, "HEADERS: stream_id == 0");
  3664. }
  3665. if ((stream->shut_flags & NGHTTP2_SHUT_RD)) {
  3666. /* half closed (remote): from the spec:
  3667. If an endpoint receives additional frames for a stream that is
  3668. in this state it MUST respond with a stream error (Section
  3669. 5.4.2) of type STREAM_CLOSED.
  3670. we go further, and make it connection error.
  3671. */
  3672. return session_inflate_handle_invalid_connection(
  3673. session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed");
  3674. }
  3675. if (nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
  3676. if (stream->state == NGHTTP2_STREAM_OPENED) {
  3677. rv = session_call_on_begin_headers(session, frame);
  3678. if (rv != 0) {
  3679. return rv;
  3680. }
  3681. return 0;
  3682. }
  3683. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3684. }
  3685. /* If this is remote peer initiated stream, it is OK unless it
  3686. has sent END_STREAM frame already. But if stream is in
  3687. NGHTTP2_STREAM_CLOSING, we discard the frame. This is a race
  3688. condition. */
  3689. if (stream->state != NGHTTP2_STREAM_CLOSING) {
  3690. rv = session_call_on_begin_headers(session, frame);
  3691. if (rv != 0) {
  3692. return rv;
  3693. }
  3694. return 0;
  3695. }
  3696. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  3697. }
  3698. static int session_process_headers_frame(nghttp2_session *session) {
  3699. nghttp2_inbound_frame *iframe = &session->iframe;
  3700. nghttp2_frame *frame = &iframe->frame;
  3701. nghttp2_stream *stream;
  3702. nghttp2_frame_unpack_headers_payload(&frame->headers, iframe->sbuf.pos);
  3703. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  3704. if (!stream) {
  3705. frame->headers.cat = NGHTTP2_HCAT_REQUEST;
  3706. return nghttp2_session_on_request_headers_received(session, frame);
  3707. }
  3708. if (stream->state == NGHTTP2_STREAM_RESERVED) {
  3709. frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE;
  3710. return nghttp2_session_on_push_response_headers_received(session, frame,
  3711. stream);
  3712. }
  3713. if (stream->state == NGHTTP2_STREAM_OPENING &&
  3714. nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
  3715. frame->headers.cat = NGHTTP2_HCAT_RESPONSE;
  3716. return nghttp2_session_on_response_headers_received(session, frame, stream);
  3717. }
  3718. frame->headers.cat = NGHTTP2_HCAT_HEADERS;
  3719. return nghttp2_session_on_headers_received(session, frame, stream);
  3720. }
  3721. int nghttp2_session_on_priority_received(nghttp2_session *session,
  3722. nghttp2_frame *frame) {
  3723. int rv;
  3724. nghttp2_stream *stream;
  3725. assert(!session_no_rfc7540_pri_no_fallback(session));
  3726. if (frame->hd.stream_id == 0) {
  3727. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  3728. "PRIORITY: stream_id == 0");
  3729. }
  3730. if (frame->priority.pri_spec.stream_id == frame->hd.stream_id) {
  3731. return nghttp2_session_terminate_session_with_reason(
  3732. session, NGHTTP2_PROTOCOL_ERROR, "depend on itself");
  3733. }
  3734. if (!session->server) {
  3735. /* Re-prioritization works only in server */
  3736. return session_call_on_frame_received(session, frame);
  3737. }
  3738. stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
  3739. if (!stream) {
  3740. /* PRIORITY against idle stream can create anchor node in
  3741. dependency tree. */
  3742. if (!session_detect_idle_stream(session, frame->hd.stream_id)) {
  3743. return 0;
  3744. }
  3745. stream = nghttp2_session_open_stream(
  3746. session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE,
  3747. &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL);
  3748. if (stream == NULL) {
  3749. return NGHTTP2_ERR_NOMEM;
  3750. }
  3751. rv = nghttp2_session_adjust_idle_stream(session);
  3752. if (nghttp2_is_fatal(rv)) {
  3753. return rv;
  3754. }
  3755. } else {
  3756. rv = nghttp2_session_reprioritize_stream(session, stream,
  3757. &frame->priority.pri_spec);
  3758. if (nghttp2_is_fatal(rv)) {
  3759. return rv;
  3760. }
  3761. rv = nghttp2_session_adjust_idle_stream(session);
  3762. if (nghttp2_is_fatal(rv)) {
  3763. return rv;
  3764. }
  3765. }
  3766. return session_call_on_frame_received(session, frame);
  3767. }
  3768. static int session_process_priority_frame(nghttp2_session *session) {
  3769. nghttp2_inbound_frame *iframe = &session->iframe;
  3770. nghttp2_frame *frame = &iframe->frame;
  3771. assert(!session_no_rfc7540_pri_no_fallback(session));
  3772. nghttp2_frame_unpack_priority_payload(&frame->priority, iframe->sbuf.pos);
  3773. return nghttp2_session_on_priority_received(session, frame);
  3774. }
  3775. static int session_update_stream_reset_ratelim(nghttp2_session *session) {
  3776. if (!session->server || (session->goaway_flags & NGHTTP2_GOAWAY_SUBMITTED)) {
  3777. return 0;
  3778. }
  3779. nghttp2_ratelim_update(&session->stream_reset_ratelim,
  3780. nghttp2_time_now_sec());
  3781. if (nghttp2_ratelim_drain(&session->stream_reset_ratelim, 1) == 0) {
  3782. return 0;
  3783. }
  3784. return nghttp2_session_add_goaway(session, session->last_recv_stream_id,
  3785. NGHTTP2_INTERNAL_ERROR, NULL, 0,
  3786. NGHTTP2_GOAWAY_AUX_NONE);
  3787. }
  3788. int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
  3789. nghttp2_frame *frame) {
  3790. int rv;
  3791. nghttp2_stream *stream;
  3792. if (frame->hd.stream_id == 0) {
  3793. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  3794. "RST_STREAM: stream_id == 0");
  3795. }
  3796. if (session_detect_idle_stream(session, frame->hd.stream_id)) {
  3797. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  3798. "RST_STREAM: stream in idle");
  3799. }
  3800. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  3801. if (stream) {
  3802. /* We may use stream->shut_flags for strict error checking. */
  3803. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
  3804. }
  3805. rv = session_call_on_frame_received(session, frame);
  3806. if (rv != 0) {
  3807. return rv;
  3808. }
  3809. rv = nghttp2_session_close_stream(session, frame->hd.stream_id,
  3810. frame->rst_stream.error_code);
  3811. if (nghttp2_is_fatal(rv)) {
  3812. return rv;
  3813. }
  3814. return session_update_stream_reset_ratelim(session);
  3815. }
  3816. static int session_process_rst_stream_frame(nghttp2_session *session) {
  3817. nghttp2_inbound_frame *iframe = &session->iframe;
  3818. nghttp2_frame *frame = &iframe->frame;
  3819. nghttp2_frame_unpack_rst_stream_payload(&frame->rst_stream, iframe->sbuf.pos);
  3820. return nghttp2_session_on_rst_stream_received(session, frame);
  3821. }
  3822. static int update_remote_initial_window_size_func(void *entry, void *ptr) {
  3823. int rv;
  3824. nghttp2_update_window_size_arg *arg;
  3825. nghttp2_stream *stream;
  3826. arg = (nghttp2_update_window_size_arg *)ptr;
  3827. stream = (nghttp2_stream *)entry;
  3828. rv = nghttp2_stream_update_remote_initial_window_size(
  3829. stream, arg->new_window_size, arg->old_window_size);
  3830. if (rv != 0) {
  3831. return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
  3832. NGHTTP2_FLOW_CONTROL_ERROR);
  3833. }
  3834. /* If window size gets positive, push deferred DATA frame to
  3835. outbound queue. */
  3836. if (stream->remote_window_size > 0 &&
  3837. nghttp2_stream_check_deferred_by_flow_control(stream)) {
  3838. rv = session_resume_deferred_stream_item(
  3839. arg->session, stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
  3840. if (nghttp2_is_fatal(rv)) {
  3841. return rv;
  3842. }
  3843. }
  3844. return 0;
  3845. }
  3846. /*
  3847. * Updates the remote initial window size of all active streams. If
  3848. * error occurs, all streams may not be updated.
  3849. *
  3850. * This function returns 0 if it succeeds, or one of the following
  3851. * negative error codes:
  3852. *
  3853. * NGHTTP2_ERR_NOMEM
  3854. * Out of memory.
  3855. */
  3856. static int
  3857. session_update_remote_initial_window_size(nghttp2_session *session,
  3858. int32_t new_initial_window_size) {
  3859. nghttp2_update_window_size_arg arg;
  3860. arg.session = session;
  3861. arg.new_window_size = new_initial_window_size;
  3862. arg.old_window_size = (int32_t)session->remote_settings.initial_window_size;
  3863. return nghttp2_map_each(&session->streams,
  3864. update_remote_initial_window_size_func, &arg);
  3865. }
  3866. static int update_local_initial_window_size_func(void *entry, void *ptr) {
  3867. int rv;
  3868. nghttp2_update_window_size_arg *arg;
  3869. nghttp2_stream *stream;
  3870. arg = (nghttp2_update_window_size_arg *)ptr;
  3871. stream = (nghttp2_stream *)entry;
  3872. rv = nghttp2_stream_update_local_initial_window_size(
  3873. stream, arg->new_window_size, arg->old_window_size);
  3874. if (rv != 0) {
  3875. return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
  3876. NGHTTP2_FLOW_CONTROL_ERROR);
  3877. }
  3878. if (stream->window_update_queued) {
  3879. return 0;
  3880. }
  3881. if (arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
  3882. return session_update_stream_consumed_size(arg->session, stream, 0);
  3883. }
  3884. if (nghttp2_should_send_window_update(stream->local_window_size,
  3885. stream->recv_window_size)) {
  3886. rv = nghttp2_session_add_window_update(arg->session, NGHTTP2_FLAG_NONE,
  3887. stream->stream_id,
  3888. stream->recv_window_size);
  3889. if (rv != 0) {
  3890. return rv;
  3891. }
  3892. stream->recv_window_size = 0;
  3893. }
  3894. return 0;
  3895. }
  3896. /*
  3897. * Updates the local initial window size of all active streams. If
  3898. * error occurs, all streams may not be updated.
  3899. *
  3900. * This function returns 0 if it succeeds, or one of the following
  3901. * negative error codes:
  3902. *
  3903. * NGHTTP2_ERR_NOMEM
  3904. * Out of memory.
  3905. */
  3906. static int
  3907. session_update_local_initial_window_size(nghttp2_session *session,
  3908. int32_t new_initial_window_size,
  3909. int32_t old_initial_window_size) {
  3910. nghttp2_update_window_size_arg arg;
  3911. arg.session = session;
  3912. arg.new_window_size = new_initial_window_size;
  3913. arg.old_window_size = old_initial_window_size;
  3914. return nghttp2_map_each(&session->streams,
  3915. update_local_initial_window_size_func, &arg);
  3916. }
  3917. /*
  3918. * Apply SETTINGS values |iv| having |niv| elements to the local
  3919. * settings. We assumes that all values in |iv| is correct, since we
  3920. * validated them in nghttp2_session_add_settings() already.
  3921. *
  3922. * This function returns 0 if it succeeds, or one of the following
  3923. * negative error codes:
  3924. *
  3925. * NGHTTP2_ERR_HEADER_COMP
  3926. * The header table size is out of range
  3927. * NGHTTP2_ERR_NOMEM
  3928. * Out of memory
  3929. */
  3930. int nghttp2_session_update_local_settings(nghttp2_session *session,
  3931. nghttp2_settings_entry *iv,
  3932. size_t niv) {
  3933. int rv;
  3934. size_t i;
  3935. int32_t new_initial_window_size = -1;
  3936. uint32_t header_table_size = 0;
  3937. uint32_t min_header_table_size = UINT32_MAX;
  3938. uint8_t header_table_size_seen = 0;
  3939. /* For NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, use the value last
  3940. seen. For NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, use both minimum
  3941. value and last seen value. */
  3942. for (i = 0; i < niv; ++i) {
  3943. switch (iv[i].settings_id) {
  3944. case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
  3945. header_table_size_seen = 1;
  3946. header_table_size = iv[i].value;
  3947. min_header_table_size =
  3948. nghttp2_min_uint32(min_header_table_size, iv[i].value);
  3949. break;
  3950. case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
  3951. new_initial_window_size = (int32_t)iv[i].value;
  3952. break;
  3953. }
  3954. }
  3955. if (header_table_size_seen) {
  3956. if (min_header_table_size < header_table_size) {
  3957. rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater,
  3958. min_header_table_size);
  3959. if (rv != 0) {
  3960. return rv;
  3961. }
  3962. }
  3963. rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater,
  3964. header_table_size);
  3965. if (rv != 0) {
  3966. return rv;
  3967. }
  3968. }
  3969. if (new_initial_window_size != -1) {
  3970. rv = session_update_local_initial_window_size(
  3971. session, new_initial_window_size,
  3972. (int32_t)session->local_settings.initial_window_size);
  3973. if (rv != 0) {
  3974. return rv;
  3975. }
  3976. }
  3977. for (i = 0; i < niv; ++i) {
  3978. switch (iv[i].settings_id) {
  3979. case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
  3980. session->local_settings.header_table_size = iv[i].value;
  3981. break;
  3982. case NGHTTP2_SETTINGS_ENABLE_PUSH:
  3983. session->local_settings.enable_push = iv[i].value;
  3984. break;
  3985. case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
  3986. session->local_settings.max_concurrent_streams = iv[i].value;
  3987. break;
  3988. case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
  3989. session->local_settings.initial_window_size = iv[i].value;
  3990. break;
  3991. case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
  3992. session->local_settings.max_frame_size = iv[i].value;
  3993. break;
  3994. case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
  3995. session->local_settings.max_header_list_size = iv[i].value;
  3996. break;
  3997. case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
  3998. session->local_settings.enable_connect_protocol = iv[i].value;
  3999. break;
  4000. case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
  4001. session->local_settings.no_rfc7540_priorities = iv[i].value;
  4002. break;
  4003. }
  4004. }
  4005. return 0;
  4006. }
  4007. int nghttp2_session_on_settings_received(nghttp2_session *session,
  4008. nghttp2_frame *frame, int noack) {
  4009. int rv;
  4010. size_t i;
  4011. nghttp2_mem *mem;
  4012. nghttp2_inflight_settings *settings;
  4013. mem = &session->mem;
  4014. if (frame->hd.stream_id != 0) {
  4015. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  4016. "SETTINGS: stream_id != 0");
  4017. }
  4018. if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
  4019. if (frame->settings.niv != 0) {
  4020. return session_handle_invalid_connection(
  4021. session, frame, NGHTTP2_ERR_FRAME_SIZE_ERROR,
  4022. "SETTINGS: ACK and payload != 0");
  4023. }
  4024. settings = session->inflight_settings_head;
  4025. if (!settings) {
  4026. return session_handle_invalid_connection(
  4027. session, frame, NGHTTP2_ERR_PROTO, "SETTINGS: unexpected ACK");
  4028. }
  4029. rv = nghttp2_session_update_local_settings(session, settings->iv,
  4030. settings->niv);
  4031. session->inflight_settings_head = settings->next;
  4032. inflight_settings_del(settings, mem);
  4033. if (rv != 0) {
  4034. if (nghttp2_is_fatal(rv)) {
  4035. return rv;
  4036. }
  4037. return session_handle_invalid_connection(session, frame, rv, NULL);
  4038. }
  4039. return session_call_on_frame_received(session, frame);
  4040. }
  4041. if (!session->remote_settings_received) {
  4042. session->remote_settings.max_concurrent_streams =
  4043. NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
  4044. session->remote_settings_received = 1;
  4045. }
  4046. for (i = 0; i < frame->settings.niv; ++i) {
  4047. nghttp2_settings_entry *entry = &frame->settings.iv[i];
  4048. switch (entry->settings_id) {
  4049. case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
  4050. rv = nghttp2_hd_deflate_change_table_size(&session->hd_deflater,
  4051. entry->value);
  4052. if (rv != 0) {
  4053. if (nghttp2_is_fatal(rv)) {
  4054. return rv;
  4055. } else {
  4056. return session_handle_invalid_connection(
  4057. session, frame, NGHTTP2_ERR_HEADER_COMP, NULL);
  4058. }
  4059. }
  4060. session->remote_settings.header_table_size = entry->value;
  4061. break;
  4062. case NGHTTP2_SETTINGS_ENABLE_PUSH:
  4063. if (entry->value != 0 && entry->value != 1) {
  4064. return session_handle_invalid_connection(
  4065. session, frame, NGHTTP2_ERR_PROTO,
  4066. "SETTINGS: invalid SETTINGS_ENBLE_PUSH");
  4067. }
  4068. if (!session->server && entry->value != 0) {
  4069. return session_handle_invalid_connection(
  4070. session, frame, NGHTTP2_ERR_PROTO,
  4071. "SETTINGS: server attempted to enable push");
  4072. }
  4073. session->remote_settings.enable_push = entry->value;
  4074. break;
  4075. case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
  4076. session->remote_settings.max_concurrent_streams = entry->value;
  4077. break;
  4078. case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
  4079. /* Update the initial window size of the all active streams */
  4080. /* Check that initial_window_size < (1u << 31) */
  4081. if (entry->value > NGHTTP2_MAX_WINDOW_SIZE) {
  4082. return session_handle_invalid_connection(
  4083. session, frame, NGHTTP2_ERR_FLOW_CONTROL,
  4084. "SETTINGS: too large SETTINGS_INITIAL_WINDOW_SIZE");
  4085. }
  4086. rv = session_update_remote_initial_window_size(session,
  4087. (int32_t)entry->value);
  4088. if (nghttp2_is_fatal(rv)) {
  4089. return rv;
  4090. }
  4091. if (rv != 0) {
  4092. return session_handle_invalid_connection(
  4093. session, frame, NGHTTP2_ERR_FLOW_CONTROL, NULL);
  4094. }
  4095. session->remote_settings.initial_window_size = entry->value;
  4096. break;
  4097. case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
  4098. if (entry->value < NGHTTP2_MAX_FRAME_SIZE_MIN ||
  4099. entry->value > NGHTTP2_MAX_FRAME_SIZE_MAX) {
  4100. return session_handle_invalid_connection(
  4101. session, frame, NGHTTP2_ERR_PROTO,
  4102. "SETTINGS: invalid SETTINGS_MAX_FRAME_SIZE");
  4103. }
  4104. session->remote_settings.max_frame_size = entry->value;
  4105. break;
  4106. case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
  4107. session->remote_settings.max_header_list_size = entry->value;
  4108. break;
  4109. case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
  4110. if (entry->value != 0 && entry->value != 1) {
  4111. return session_handle_invalid_connection(
  4112. session, frame, NGHTTP2_ERR_PROTO,
  4113. "SETTINGS: invalid SETTINGS_ENABLE_CONNECT_PROTOCOL");
  4114. }
  4115. if (!session->server &&
  4116. session->remote_settings.enable_connect_protocol &&
  4117. entry->value == 0) {
  4118. return session_handle_invalid_connection(
  4119. session, frame, NGHTTP2_ERR_PROTO,
  4120. "SETTINGS: server attempted to disable "
  4121. "SETTINGS_ENABLE_CONNECT_PROTOCOL");
  4122. }
  4123. session->remote_settings.enable_connect_protocol = entry->value;
  4124. break;
  4125. case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
  4126. if (entry->value != 0 && entry->value != 1) {
  4127. return session_handle_invalid_connection(
  4128. session, frame, NGHTTP2_ERR_PROTO,
  4129. "SETTINGS: invalid SETTINGS_NO_RFC7540_PRIORITIES");
  4130. }
  4131. if (session->remote_settings.no_rfc7540_priorities != UINT32_MAX &&
  4132. session->remote_settings.no_rfc7540_priorities != entry->value) {
  4133. return session_handle_invalid_connection(
  4134. session, frame, NGHTTP2_ERR_PROTO,
  4135. "SETTINGS: SETTINGS_NO_RFC7540_PRIORITIES cannot be changed");
  4136. }
  4137. session->remote_settings.no_rfc7540_priorities = entry->value;
  4138. break;
  4139. }
  4140. }
  4141. if (session->remote_settings.no_rfc7540_priorities == UINT32_MAX) {
  4142. session->remote_settings.no_rfc7540_priorities = 0;
  4143. if (session->server && session->pending_no_rfc7540_priorities &&
  4144. (session->opt_flags &
  4145. NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES)) {
  4146. session->fallback_rfc7540_priorities = 1;
  4147. }
  4148. }
  4149. if (!noack && !session_is_closing(session)) {
  4150. rv = nghttp2_session_add_settings(session, NGHTTP2_FLAG_ACK, NULL, 0);
  4151. if (rv != 0) {
  4152. if (nghttp2_is_fatal(rv)) {
  4153. return rv;
  4154. }
  4155. return session_handle_invalid_connection(session, frame,
  4156. NGHTTP2_ERR_INTERNAL, NULL);
  4157. }
  4158. }
  4159. return session_call_on_frame_received(session, frame);
  4160. }
  4161. static int session_process_settings_frame(nghttp2_session *session) {
  4162. nghttp2_inbound_frame *iframe = &session->iframe;
  4163. nghttp2_frame *frame = &iframe->frame;
  4164. size_t i;
  4165. nghttp2_settings_entry min_header_size_entry;
  4166. if (iframe->max_niv) {
  4167. min_header_size_entry = iframe->iv[iframe->max_niv - 1];
  4168. if (min_header_size_entry.value < UINT32_MAX) {
  4169. /* If we have less value, then we must have
  4170. SETTINGS_HEADER_TABLE_SIZE in i < iframe->niv */
  4171. for (i = 0; i < iframe->niv; ++i) {
  4172. if (iframe->iv[i].settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) {
  4173. break;
  4174. }
  4175. }
  4176. assert(i < iframe->niv);
  4177. if (min_header_size_entry.value != iframe->iv[i].value) {
  4178. iframe->iv[iframe->niv++] = iframe->iv[i];
  4179. iframe->iv[i] = min_header_size_entry;
  4180. }
  4181. }
  4182. }
  4183. nghttp2_frame_unpack_settings_payload(&frame->settings, iframe->iv,
  4184. iframe->niv);
  4185. iframe->iv = NULL;
  4186. iframe->niv = 0;
  4187. iframe->max_niv = 0;
  4188. return nghttp2_session_on_settings_received(session, frame, 0 /* ACK */);
  4189. }
  4190. int nghttp2_session_on_push_promise_received(nghttp2_session *session,
  4191. nghttp2_frame *frame) {
  4192. int rv;
  4193. nghttp2_stream *stream;
  4194. nghttp2_stream *promised_stream;
  4195. nghttp2_priority_spec pri_spec;
  4196. if (frame->hd.stream_id == 0) {
  4197. return session_inflate_handle_invalid_connection(
  4198. session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream_id == 0");
  4199. }
  4200. if (session->server || session->local_settings.enable_push == 0) {
  4201. return session_inflate_handle_invalid_connection(
  4202. session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: push disabled");
  4203. }
  4204. if (!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
  4205. return session_inflate_handle_invalid_connection(
  4206. session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: invalid stream_id");
  4207. }
  4208. if (!session_allow_incoming_new_stream(session)) {
  4209. /* We just discard PUSH_PROMISE after GOAWAY was sent */
  4210. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  4211. }
  4212. if (!session_is_new_peer_stream_id(session,
  4213. frame->push_promise.promised_stream_id)) {
  4214. /* The spec says if an endpoint receives a PUSH_PROMISE with
  4215. illegal stream ID is subject to a connection error of type
  4216. PROTOCOL_ERROR. */
  4217. return session_inflate_handle_invalid_connection(
  4218. session, frame, NGHTTP2_ERR_PROTO,
  4219. "PUSH_PROMISE: invalid promised_stream_id");
  4220. }
  4221. if (session_detect_idle_stream(session, frame->hd.stream_id)) {
  4222. return session_inflate_handle_invalid_connection(
  4223. session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream in idle");
  4224. }
  4225. session->last_recv_stream_id = frame->push_promise.promised_stream_id;
  4226. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  4227. if (!stream || stream->state == NGHTTP2_STREAM_CLOSING ||
  4228. !session->pending_enable_push ||
  4229. session->num_incoming_reserved_streams >=
  4230. session->max_incoming_reserved_streams) {
  4231. /* Currently, client does not retain closed stream, so we don't
  4232. check NGHTTP2_SHUT_RD condition here. */
  4233. rv = nghttp2_session_add_rst_stream(
  4234. session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL);
  4235. if (rv != 0) {
  4236. return rv;
  4237. }
  4238. return NGHTTP2_ERR_IGN_HEADER_BLOCK;
  4239. }
  4240. if (stream->shut_flags & NGHTTP2_SHUT_RD) {
  4241. return session_inflate_handle_invalid_connection(
  4242. session, frame, NGHTTP2_ERR_STREAM_CLOSED, "PUSH_PROMISE: stream closed");
  4243. }
  4244. nghttp2_priority_spec_init(&pri_spec, stream->stream_id,
  4245. NGHTTP2_DEFAULT_WEIGHT, 0);
  4246. promised_stream = nghttp2_session_open_stream(
  4247. session, frame->push_promise.promised_stream_id, NGHTTP2_STREAM_FLAG_NONE,
  4248. &pri_spec, NGHTTP2_STREAM_RESERVED, NULL);
  4249. if (!promised_stream) {
  4250. return NGHTTP2_ERR_NOMEM;
  4251. }
  4252. /* We don't call nghttp2_session_adjust_closed_stream(), since we
  4253. don't keep closed stream in client side */
  4254. session->last_proc_stream_id = session->last_recv_stream_id;
  4255. rv = session_call_on_begin_headers(session, frame);
  4256. if (rv != 0) {
  4257. return rv;
  4258. }
  4259. return 0;
  4260. }
  4261. static int session_process_push_promise_frame(nghttp2_session *session) {
  4262. nghttp2_inbound_frame *iframe = &session->iframe;
  4263. nghttp2_frame *frame = &iframe->frame;
  4264. nghttp2_frame_unpack_push_promise_payload(&frame->push_promise,
  4265. iframe->sbuf.pos);
  4266. return nghttp2_session_on_push_promise_received(session, frame);
  4267. }
  4268. int nghttp2_session_on_ping_received(nghttp2_session *session,
  4269. nghttp2_frame *frame) {
  4270. int rv = 0;
  4271. if (frame->hd.stream_id != 0) {
  4272. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  4273. "PING: stream_id != 0");
  4274. }
  4275. if ((session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK) == 0 &&
  4276. (frame->hd.flags & NGHTTP2_FLAG_ACK) == 0 &&
  4277. !session_is_closing(session)) {
  4278. /* Peer sent ping, so ping it back */
  4279. rv = nghttp2_session_add_ping(session, NGHTTP2_FLAG_ACK,
  4280. frame->ping.opaque_data);
  4281. if (rv != 0) {
  4282. return rv;
  4283. }
  4284. }
  4285. return session_call_on_frame_received(session, frame);
  4286. }
  4287. static int session_process_ping_frame(nghttp2_session *session) {
  4288. nghttp2_inbound_frame *iframe = &session->iframe;
  4289. nghttp2_frame *frame = &iframe->frame;
  4290. nghttp2_frame_unpack_ping_payload(&frame->ping, iframe->sbuf.pos);
  4291. return nghttp2_session_on_ping_received(session, frame);
  4292. }
  4293. int nghttp2_session_on_goaway_received(nghttp2_session *session,
  4294. nghttp2_frame *frame) {
  4295. int rv;
  4296. if (frame->hd.stream_id != 0) {
  4297. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  4298. "GOAWAY: stream_id != 0");
  4299. }
  4300. /* Spec says Endpoints MUST NOT increase the value they send in the
  4301. last stream identifier. */
  4302. if ((frame->goaway.last_stream_id > 0 &&
  4303. !nghttp2_session_is_my_stream_id(session,
  4304. frame->goaway.last_stream_id)) ||
  4305. session->remote_last_stream_id < frame->goaway.last_stream_id) {
  4306. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  4307. "GOAWAY: invalid last_stream_id");
  4308. }
  4309. session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
  4310. session->remote_last_stream_id = frame->goaway.last_stream_id;
  4311. rv = session_call_on_frame_received(session, frame);
  4312. if (nghttp2_is_fatal(rv)) {
  4313. return rv;
  4314. }
  4315. return session_close_stream_on_goaway(session, frame->goaway.last_stream_id,
  4316. 0);
  4317. }
  4318. static int session_process_goaway_frame(nghttp2_session *session) {
  4319. nghttp2_inbound_frame *iframe = &session->iframe;
  4320. nghttp2_frame *frame = &iframe->frame;
  4321. nghttp2_frame_unpack_goaway_payload(&frame->goaway, iframe->sbuf.pos,
  4322. iframe->lbuf.pos,
  4323. nghttp2_buf_len(&iframe->lbuf));
  4324. nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
  4325. return nghttp2_session_on_goaway_received(session, frame);
  4326. }
  4327. static int
  4328. session_on_connection_window_update_received(nghttp2_session *session,
  4329. nghttp2_frame *frame) {
  4330. /* Handle connection-level flow control */
  4331. if (frame->window_update.window_size_increment == 0) {
  4332. return session_handle_invalid_connection(
  4333. session, frame, NGHTTP2_ERR_PROTO,
  4334. "WINDOW_UPDATE: window_size_increment == 0");
  4335. }
  4336. if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
  4337. session->remote_window_size) {
  4338. return session_handle_invalid_connection(session, frame,
  4339. NGHTTP2_ERR_FLOW_CONTROL, NULL);
  4340. }
  4341. session->remote_window_size += frame->window_update.window_size_increment;
  4342. return session_call_on_frame_received(session, frame);
  4343. }
  4344. static int session_on_stream_window_update_received(nghttp2_session *session,
  4345. nghttp2_frame *frame) {
  4346. int rv;
  4347. nghttp2_stream *stream;
  4348. if (session_detect_idle_stream(session, frame->hd.stream_id)) {
  4349. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  4350. "WINDOW_UPDATE to idle stream");
  4351. }
  4352. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  4353. if (!stream) {
  4354. return 0;
  4355. }
  4356. if (state_reserved_remote(session, stream)) {
  4357. return session_handle_invalid_connection(
  4358. session, frame, NGHTTP2_ERR_PROTO, "WINDOW_UPADATE to reserved stream");
  4359. }
  4360. if (frame->window_update.window_size_increment == 0) {
  4361. return session_handle_invalid_connection(
  4362. session, frame, NGHTTP2_ERR_PROTO,
  4363. "WINDOW_UPDATE: window_size_increment == 0");
  4364. }
  4365. if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
  4366. stream->remote_window_size) {
  4367. return session_handle_invalid_stream(session, frame,
  4368. NGHTTP2_ERR_FLOW_CONTROL);
  4369. }
  4370. stream->remote_window_size += frame->window_update.window_size_increment;
  4371. if (stream->remote_window_size > 0 &&
  4372. nghttp2_stream_check_deferred_by_flow_control(stream)) {
  4373. rv = session_resume_deferred_stream_item(
  4374. session, stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
  4375. if (nghttp2_is_fatal(rv)) {
  4376. return rv;
  4377. }
  4378. }
  4379. return session_call_on_frame_received(session, frame);
  4380. }
  4381. int nghttp2_session_on_window_update_received(nghttp2_session *session,
  4382. nghttp2_frame *frame) {
  4383. if (frame->hd.stream_id == 0) {
  4384. return session_on_connection_window_update_received(session, frame);
  4385. } else {
  4386. return session_on_stream_window_update_received(session, frame);
  4387. }
  4388. }
  4389. static int session_process_window_update_frame(nghttp2_session *session) {
  4390. nghttp2_inbound_frame *iframe = &session->iframe;
  4391. nghttp2_frame *frame = &iframe->frame;
  4392. nghttp2_frame_unpack_window_update_payload(&frame->window_update,
  4393. iframe->sbuf.pos);
  4394. return nghttp2_session_on_window_update_received(session, frame);
  4395. }
  4396. int nghttp2_session_on_altsvc_received(nghttp2_session *session,
  4397. nghttp2_frame *frame) {
  4398. nghttp2_ext_altsvc *altsvc;
  4399. nghttp2_stream *stream;
  4400. altsvc = frame->ext.payload;
  4401. /* session->server case has been excluded */
  4402. if (frame->hd.stream_id == 0) {
  4403. if (altsvc->origin_len == 0) {
  4404. return session_call_on_invalid_frame_recv_callback(session, frame,
  4405. NGHTTP2_ERR_PROTO);
  4406. }
  4407. } else {
  4408. if (altsvc->origin_len > 0) {
  4409. return session_call_on_invalid_frame_recv_callback(session, frame,
  4410. NGHTTP2_ERR_PROTO);
  4411. }
  4412. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  4413. if (!stream) {
  4414. return 0;
  4415. }
  4416. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  4417. return 0;
  4418. }
  4419. }
  4420. if (altsvc->field_value_len == 0) {
  4421. return session_call_on_invalid_frame_recv_callback(session, frame,
  4422. NGHTTP2_ERR_PROTO);
  4423. }
  4424. return session_call_on_frame_received(session, frame);
  4425. }
  4426. int nghttp2_session_on_origin_received(nghttp2_session *session,
  4427. nghttp2_frame *frame) {
  4428. return session_call_on_frame_received(session, frame);
  4429. }
  4430. int nghttp2_session_on_priority_update_received(nghttp2_session *session,
  4431. nghttp2_frame *frame) {
  4432. nghttp2_ext_priority_update *priority_update;
  4433. nghttp2_stream *stream;
  4434. nghttp2_priority_spec pri_spec;
  4435. nghttp2_extpri extpri;
  4436. int rv;
  4437. assert(session->server);
  4438. priority_update = frame->ext.payload;
  4439. if (frame->hd.stream_id != 0) {
  4440. return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
  4441. "PRIORITY_UPDATE: stream_id == 0");
  4442. }
  4443. if (nghttp2_session_is_my_stream_id(session, priority_update->stream_id)) {
  4444. if (session_detect_idle_stream(session, priority_update->stream_id)) {
  4445. return session_handle_invalid_connection(
  4446. session, frame, NGHTTP2_ERR_PROTO,
  4447. "PRIORITY_UPDATE: prioritizing idle push is not allowed");
  4448. }
  4449. /* TODO Ignore priority signal to a push stream for now */
  4450. return session_call_on_frame_received(session, frame);
  4451. }
  4452. stream = nghttp2_session_get_stream_raw(session, priority_update->stream_id);
  4453. if (stream) {
  4454. /* Stream already exists. */
  4455. if (stream->flags & NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES) {
  4456. return session_call_on_frame_received(session, frame);
  4457. }
  4458. } else if (session_detect_idle_stream(session, priority_update->stream_id)) {
  4459. if (session->num_idle_streams + session->num_incoming_streams >=
  4460. session->local_settings.max_concurrent_streams) {
  4461. return session_handle_invalid_connection(
  4462. session, frame, NGHTTP2_ERR_PROTO,
  4463. "PRIORITY_UPDATE: max concurrent streams exceeded");
  4464. }
  4465. nghttp2_priority_spec_default_init(&pri_spec);
  4466. stream = nghttp2_session_open_stream(session, priority_update->stream_id,
  4467. NGHTTP2_FLAG_NONE, &pri_spec,
  4468. NGHTTP2_STREAM_IDLE, NULL);
  4469. if (!stream) {
  4470. return NGHTTP2_ERR_NOMEM;
  4471. }
  4472. } else {
  4473. return session_call_on_frame_received(session, frame);
  4474. }
  4475. extpri.urgency = NGHTTP2_EXTPRI_DEFAULT_URGENCY;
  4476. extpri.inc = 0;
  4477. rv = nghttp2_http_parse_priority(&extpri, priority_update->field_value,
  4478. priority_update->field_value_len);
  4479. if (rv != 0) {
  4480. /* Just ignore field_value if it cannot be parsed. */
  4481. return session_call_on_frame_received(session, frame);
  4482. }
  4483. rv = session_update_stream_priority(session, stream,
  4484. nghttp2_extpri_to_uint8(&extpri));
  4485. if (rv != 0) {
  4486. if (nghttp2_is_fatal(rv)) {
  4487. return rv;
  4488. }
  4489. }
  4490. return session_call_on_frame_received(session, frame);
  4491. }
  4492. static int session_process_altsvc_frame(nghttp2_session *session) {
  4493. nghttp2_inbound_frame *iframe = &session->iframe;
  4494. nghttp2_frame *frame = &iframe->frame;
  4495. nghttp2_frame_unpack_altsvc_payload(
  4496. &frame->ext, nghttp2_get_uint16(iframe->sbuf.pos), iframe->lbuf.pos,
  4497. nghttp2_buf_len(&iframe->lbuf));
  4498. /* nghttp2_frame_unpack_altsvc_payload steals buffer from
  4499. iframe->lbuf */
  4500. nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
  4501. return nghttp2_session_on_altsvc_received(session, frame);
  4502. }
  4503. static int session_process_origin_frame(nghttp2_session *session) {
  4504. nghttp2_inbound_frame *iframe = &session->iframe;
  4505. nghttp2_frame *frame = &iframe->frame;
  4506. nghttp2_mem *mem = &session->mem;
  4507. int rv;
  4508. rv = nghttp2_frame_unpack_origin_payload(&frame->ext, iframe->lbuf.pos,
  4509. nghttp2_buf_len(&iframe->lbuf), mem);
  4510. if (rv != 0) {
  4511. if (nghttp2_is_fatal(rv)) {
  4512. return rv;
  4513. }
  4514. /* Ignore ORIGIN frame which cannot be parsed. */
  4515. return 0;
  4516. }
  4517. return nghttp2_session_on_origin_received(session, frame);
  4518. }
  4519. static int session_process_priority_update_frame(nghttp2_session *session) {
  4520. nghttp2_inbound_frame *iframe = &session->iframe;
  4521. nghttp2_frame *frame = &iframe->frame;
  4522. nghttp2_frame_unpack_priority_update_payload(&frame->ext, iframe->sbuf.pos,
  4523. nghttp2_buf_len(&iframe->sbuf));
  4524. return nghttp2_session_on_priority_update_received(session, frame);
  4525. }
  4526. static int session_process_extension_frame(nghttp2_session *session) {
  4527. int rv;
  4528. nghttp2_inbound_frame *iframe = &session->iframe;
  4529. nghttp2_frame *frame = &iframe->frame;
  4530. rv = session_call_unpack_extension_callback(session);
  4531. if (nghttp2_is_fatal(rv)) {
  4532. return rv;
  4533. }
  4534. /* This handles the case where rv == NGHTTP2_ERR_CANCEL as well */
  4535. if (rv != 0) {
  4536. return 0;
  4537. }
  4538. return session_call_on_frame_received(session, frame);
  4539. }
  4540. int nghttp2_session_on_data_received(nghttp2_session *session,
  4541. nghttp2_frame *frame) {
  4542. int rv = 0;
  4543. nghttp2_stream *stream;
  4544. /* We don't call on_frame_recv_callback if stream has been closed
  4545. already or being closed. */
  4546. stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
  4547. if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) {
  4548. /* This should be treated as stream error, but it results in lots
  4549. of RST_STREAM. So just ignore frame against nonexistent stream
  4550. for now. */
  4551. return 0;
  4552. }
  4553. if (session_enforce_http_messaging(session) &&
  4554. (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
  4555. if (nghttp2_http_on_remote_end_stream(stream) != 0) {
  4556. rv = nghttp2_session_add_rst_stream(session, stream->stream_id,
  4557. NGHTTP2_PROTOCOL_ERROR);
  4558. if (nghttp2_is_fatal(rv)) {
  4559. return rv;
  4560. }
  4561. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
  4562. /* Don't call nghttp2_session_close_stream_if_shut_rdwr because
  4563. RST_STREAM has been submitted. */
  4564. return 0;
  4565. }
  4566. }
  4567. rv = session_call_on_frame_received(session, frame);
  4568. if (nghttp2_is_fatal(rv)) {
  4569. return rv;
  4570. }
  4571. if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
  4572. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
  4573. rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
  4574. if (nghttp2_is_fatal(rv)) {
  4575. return rv;
  4576. }
  4577. }
  4578. return 0;
  4579. }
  4580. /* For errors, this function only returns FATAL error. */
  4581. static int session_process_data_frame(nghttp2_session *session) {
  4582. int rv;
  4583. nghttp2_frame *public_data_frame = &session->iframe.frame;
  4584. rv = nghttp2_session_on_data_received(session, public_data_frame);
  4585. if (nghttp2_is_fatal(rv)) {
  4586. return rv;
  4587. }
  4588. return 0;
  4589. }
  4590. /*
  4591. * Now we have SETTINGS synchronization, flow control error can be
  4592. * detected strictly. If DATA frame is received with length > 0 and
  4593. * current received window size + delta length is strictly larger than
  4594. * local window size, it is subject to FLOW_CONTROL_ERROR, so return
  4595. * -1. Note that local_window_size is calculated after SETTINGS ACK is
  4596. * received from peer, so peer must honor this limit. If the resulting
  4597. * recv_window_size is strictly larger than NGHTTP2_MAX_WINDOW_SIZE,
  4598. * return -1 too.
  4599. */
  4600. static int adjust_recv_window_size(int32_t *recv_window_size_ptr, size_t delta,
  4601. int32_t local_window_size) {
  4602. if (*recv_window_size_ptr > local_window_size - (int32_t)delta ||
  4603. *recv_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - (int32_t)delta) {
  4604. return -1;
  4605. }
  4606. *recv_window_size_ptr += (int32_t)delta;
  4607. return 0;
  4608. }
  4609. int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
  4610. nghttp2_stream *stream,
  4611. size_t delta_size,
  4612. int send_window_update) {
  4613. int rv;
  4614. rv = adjust_recv_window_size(&stream->recv_window_size, delta_size,
  4615. stream->local_window_size);
  4616. if (rv != 0) {
  4617. return nghttp2_session_add_rst_stream(session, stream->stream_id,
  4618. NGHTTP2_FLOW_CONTROL_ERROR);
  4619. }
  4620. /* We don't have to send WINDOW_UPDATE if the data received is the
  4621. last chunk in the incoming stream. */
  4622. /* We have to use local_settings here because it is the constraint
  4623. the remote endpoint should honor. */
  4624. if (send_window_update &&
  4625. !(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
  4626. stream->window_update_queued == 0 &&
  4627. nghttp2_should_send_window_update(stream->local_window_size,
  4628. stream->recv_window_size)) {
  4629. rv = nghttp2_session_add_window_update(
  4630. session, NGHTTP2_FLAG_NONE, stream->stream_id, stream->recv_window_size);
  4631. if (rv != 0) {
  4632. return rv;
  4633. }
  4634. stream->recv_window_size = 0;
  4635. }
  4636. return 0;
  4637. }
  4638. int nghttp2_session_update_recv_connection_window_size(nghttp2_session *session,
  4639. size_t delta_size) {
  4640. int rv;
  4641. rv = adjust_recv_window_size(&session->recv_window_size, delta_size,
  4642. session->local_window_size);
  4643. if (rv != 0) {
  4644. return nghttp2_session_terminate_session(session,
  4645. NGHTTP2_FLOW_CONTROL_ERROR);
  4646. }
  4647. if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
  4648. session->window_update_queued == 0 &&
  4649. nghttp2_should_send_window_update(session->local_window_size,
  4650. session->recv_window_size)) {
  4651. /* Use stream ID 0 to update connection-level flow control
  4652. window */
  4653. rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, 0,
  4654. session->recv_window_size);
  4655. if (rv != 0) {
  4656. return rv;
  4657. }
  4658. session->recv_window_size = 0;
  4659. }
  4660. return 0;
  4661. }
  4662. static int session_update_consumed_size(nghttp2_session *session,
  4663. int32_t *consumed_size_ptr,
  4664. int32_t *recv_window_size_ptr,
  4665. uint8_t window_update_queued,
  4666. int32_t stream_id, size_t delta_size,
  4667. int32_t local_window_size) {
  4668. int32_t recv_size;
  4669. int rv;
  4670. if ((size_t)*consumed_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta_size) {
  4671. return nghttp2_session_terminate_session(session,
  4672. NGHTTP2_FLOW_CONTROL_ERROR);
  4673. }
  4674. *consumed_size_ptr += (int32_t)delta_size;
  4675. if (window_update_queued == 0) {
  4676. /* recv_window_size may be smaller than consumed_size, because it
  4677. may be decreased by negative value with
  4678. nghttp2_submit_window_update(). */
  4679. recv_size = nghttp2_min_int32(*consumed_size_ptr, *recv_window_size_ptr);
  4680. if (nghttp2_should_send_window_update(local_window_size, recv_size)) {
  4681. rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE,
  4682. stream_id, recv_size);
  4683. if (rv != 0) {
  4684. return rv;
  4685. }
  4686. *recv_window_size_ptr -= recv_size;
  4687. *consumed_size_ptr -= recv_size;
  4688. }
  4689. }
  4690. return 0;
  4691. }
  4692. static int session_update_stream_consumed_size(nghttp2_session *session,
  4693. nghttp2_stream *stream,
  4694. size_t delta_size) {
  4695. return session_update_consumed_size(
  4696. session, &stream->consumed_size, &stream->recv_window_size,
  4697. stream->window_update_queued, stream->stream_id, delta_size,
  4698. stream->local_window_size);
  4699. }
  4700. static int session_update_connection_consumed_size(nghttp2_session *session,
  4701. size_t delta_size) {
  4702. return session_update_consumed_size(
  4703. session, &session->consumed_size, &session->recv_window_size,
  4704. session->window_update_queued, 0, delta_size, session->local_window_size);
  4705. }
  4706. /*
  4707. * Checks that we can receive the DATA frame for stream, which is
  4708. * indicated by |session->iframe.frame.hd.stream_id|. If it is a
  4709. * connection error situation, GOAWAY frame will be issued by this
  4710. * function.
  4711. *
  4712. * If the DATA frame is allowed, returns 0.
  4713. *
  4714. * This function returns 0 if it succeeds, or one of the following
  4715. * negative error codes:
  4716. *
  4717. * NGHTTP2_ERR_IGN_PAYLOAD
  4718. * The reception of DATA frame is connection error; or should be
  4719. * ignored.
  4720. * NGHTTP2_ERR_NOMEM
  4721. * Out of memory.
  4722. */
  4723. static int session_on_data_received_fail_fast(nghttp2_session *session) {
  4724. int rv;
  4725. nghttp2_stream *stream;
  4726. nghttp2_inbound_frame *iframe;
  4727. int32_t stream_id;
  4728. const char *failure_reason;
  4729. uint32_t error_code = NGHTTP2_PROTOCOL_ERROR;
  4730. iframe = &session->iframe;
  4731. stream_id = iframe->frame.hd.stream_id;
  4732. if (stream_id == 0) {
  4733. /* The spec says that if a DATA frame is received whose stream ID
  4734. is 0, the recipient MUST respond with a connection error of
  4735. type PROTOCOL_ERROR. */
  4736. failure_reason = "DATA: stream_id == 0";
  4737. goto fail;
  4738. }
  4739. if (session_detect_idle_stream(session, stream_id)) {
  4740. failure_reason = "DATA: stream in idle";
  4741. error_code = NGHTTP2_PROTOCOL_ERROR;
  4742. goto fail;
  4743. }
  4744. stream = nghttp2_session_get_stream(session, stream_id);
  4745. if (!stream) {
  4746. stream = nghttp2_session_get_stream_raw(session, stream_id);
  4747. if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) {
  4748. failure_reason = "DATA: stream closed";
  4749. error_code = NGHTTP2_STREAM_CLOSED;
  4750. goto fail;
  4751. }
  4752. return NGHTTP2_ERR_IGN_PAYLOAD;
  4753. }
  4754. if (stream->shut_flags & NGHTTP2_SHUT_RD) {
  4755. failure_reason = "DATA: stream in half-closed(remote)";
  4756. error_code = NGHTTP2_STREAM_CLOSED;
  4757. goto fail;
  4758. }
  4759. if (nghttp2_session_is_my_stream_id(session, stream_id)) {
  4760. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  4761. return NGHTTP2_ERR_IGN_PAYLOAD;
  4762. }
  4763. if (stream->state != NGHTTP2_STREAM_OPENED) {
  4764. failure_reason = "DATA: stream not opened";
  4765. goto fail;
  4766. }
  4767. return 0;
  4768. }
  4769. if (stream->state == NGHTTP2_STREAM_RESERVED) {
  4770. failure_reason = "DATA: stream in reserved";
  4771. goto fail;
  4772. }
  4773. if (stream->state == NGHTTP2_STREAM_CLOSING) {
  4774. return NGHTTP2_ERR_IGN_PAYLOAD;
  4775. }
  4776. return 0;
  4777. fail:
  4778. rv = nghttp2_session_terminate_session_with_reason(session, error_code,
  4779. failure_reason);
  4780. if (nghttp2_is_fatal(rv)) {
  4781. return rv;
  4782. }
  4783. return NGHTTP2_ERR_IGN_PAYLOAD;
  4784. }
  4785. static size_t inbound_frame_payload_readlen(nghttp2_inbound_frame *iframe,
  4786. const uint8_t *in,
  4787. const uint8_t *last) {
  4788. return nghttp2_min_size((size_t)(last - in), iframe->payloadleft);
  4789. }
  4790. /*
  4791. * Resets iframe->sbuf and advance its mark pointer by |left| bytes.
  4792. */
  4793. static void inbound_frame_set_mark(nghttp2_inbound_frame *iframe, size_t left) {
  4794. nghttp2_buf_reset(&iframe->sbuf);
  4795. iframe->sbuf.mark += left;
  4796. }
  4797. static size_t inbound_frame_buf_read(nghttp2_inbound_frame *iframe,
  4798. const uint8_t *in, const uint8_t *last) {
  4799. size_t readlen;
  4800. readlen = nghttp2_min_size((size_t)(last - in),
  4801. nghttp2_buf_mark_avail(&iframe->sbuf));
  4802. iframe->sbuf.last = nghttp2_cpymem(iframe->sbuf.last, in, readlen);
  4803. return readlen;
  4804. }
  4805. /*
  4806. * Unpacks SETTINGS entry in iframe->sbuf.
  4807. */
  4808. static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) {
  4809. nghttp2_settings_entry iv;
  4810. nghttp2_settings_entry *min_header_table_size_entry;
  4811. size_t i;
  4812. nghttp2_frame_unpack_settings_entry(&iv, iframe->sbuf.pos);
  4813. switch (iv.settings_id) {
  4814. case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
  4815. case NGHTTP2_SETTINGS_ENABLE_PUSH:
  4816. case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
  4817. case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
  4818. case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
  4819. case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
  4820. case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
  4821. case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
  4822. break;
  4823. default:
  4824. DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id);
  4825. iframe->iv[iframe->niv++] = iv;
  4826. return;
  4827. }
  4828. for (i = 0; i < iframe->niv; ++i) {
  4829. if (iframe->iv[i].settings_id == iv.settings_id) {
  4830. iframe->iv[i] = iv;
  4831. break;
  4832. }
  4833. }
  4834. if (i == iframe->niv) {
  4835. iframe->iv[iframe->niv++] = iv;
  4836. }
  4837. if (iv.settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) {
  4838. /* Keep track of minimum value of SETTINGS_HEADER_TABLE_SIZE */
  4839. min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1];
  4840. if (iv.value < min_header_table_size_entry->value) {
  4841. min_header_table_size_entry->value = iv.value;
  4842. }
  4843. }
  4844. }
  4845. /*
  4846. * Checks PADDED flags and set iframe->sbuf to read them accordingly.
  4847. * If padding is set, this function returns 1. If no padding is set,
  4848. * this function returns 0. On error, returns -1.
  4849. */
  4850. static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe,
  4851. nghttp2_frame_hd *hd) {
  4852. if (hd->flags & NGHTTP2_FLAG_PADDED) {
  4853. if (hd->length < 1) {
  4854. return -1;
  4855. }
  4856. inbound_frame_set_mark(iframe, 1);
  4857. return 1;
  4858. }
  4859. DEBUGF("recv: no padding in payload\n");
  4860. return 0;
  4861. }
  4862. /*
  4863. * Computes number of padding based on flags. This function returns
  4864. * the calculated length if it succeeds, or -1.
  4865. */
  4866. static nghttp2_ssize inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) {
  4867. size_t padlen;
  4868. /* 1 for Pad Length field */
  4869. padlen = (size_t)(iframe->sbuf.pos[0] + 1);
  4870. DEBUGF("recv: padlen=%zu\n", padlen);
  4871. /* We cannot use iframe->frame.hd.length because of CONTINUATION */
  4872. if (padlen - 1 > iframe->payloadleft) {
  4873. return -1;
  4874. }
  4875. iframe->padlen = padlen;
  4876. return (nghttp2_ssize)padlen;
  4877. }
  4878. /*
  4879. * This function returns the effective payload length in the data of
  4880. * length |readlen| when the remaining payload is |payloadleft|. The
  4881. * |payloadleft| does not include |readlen|. If padding was started
  4882. * strictly before this data chunk, this function returns -1.
  4883. */
  4884. static nghttp2_ssize
  4885. inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe,
  4886. size_t payloadleft, size_t readlen) {
  4887. size_t trail_padlen =
  4888. nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
  4889. if (trail_padlen > payloadleft) {
  4890. size_t padlen;
  4891. padlen = trail_padlen - payloadleft;
  4892. if (readlen < padlen) {
  4893. return -1;
  4894. }
  4895. return (nghttp2_ssize)(readlen - padlen);
  4896. }
  4897. return (nghttp2_ssize)(readlen);
  4898. }
  4899. static const uint8_t static_in[] = {0};
  4900. ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
  4901. size_t inlen) {
  4902. return (ssize_t)nghttp2_session_mem_recv2(session, in, inlen);
  4903. }
  4904. nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
  4905. const uint8_t *in, size_t inlen) {
  4906. const uint8_t *first, *last;
  4907. nghttp2_inbound_frame *iframe = &session->iframe;
  4908. size_t readlen;
  4909. nghttp2_ssize padlen;
  4910. int rv;
  4911. int busy = 0;
  4912. nghttp2_frame_hd cont_hd;
  4913. nghttp2_stream *stream;
  4914. size_t pri_fieldlen;
  4915. nghttp2_mem *mem;
  4916. if (in == NULL) {
  4917. assert(inlen == 0);
  4918. in = static_in;
  4919. }
  4920. first = in;
  4921. last = in + inlen;
  4922. DEBUGF("recv: connection recv_window_size=%d, local_window=%d\n",
  4923. session->recv_window_size, session->local_window_size);
  4924. mem = &session->mem;
  4925. /* We may have idle streams more than we expect (e.g.,
  4926. nghttp2_session_change_stream_priority() or
  4927. nghttp2_session_create_idle_stream()). Adjust them here. */
  4928. rv = nghttp2_session_adjust_idle_stream(session);
  4929. if (nghttp2_is_fatal(rv)) {
  4930. return rv;
  4931. }
  4932. if (!nghttp2_session_want_read(session)) {
  4933. return (nghttp2_ssize)inlen;
  4934. }
  4935. for (;;) {
  4936. switch (iframe->state) {
  4937. case NGHTTP2_IB_READ_CLIENT_MAGIC:
  4938. readlen = nghttp2_min_size(inlen, iframe->payloadleft);
  4939. if (memcmp(&NGHTTP2_CLIENT_MAGIC[NGHTTP2_CLIENT_MAGIC_LEN -
  4940. iframe->payloadleft],
  4941. in, readlen) != 0) {
  4942. return NGHTTP2_ERR_BAD_CLIENT_MAGIC;
  4943. }
  4944. iframe->payloadleft -= readlen;
  4945. in += readlen;
  4946. if (iframe->payloadleft == 0) {
  4947. session_inbound_frame_reset(session);
  4948. iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS;
  4949. }
  4950. break;
  4951. case NGHTTP2_IB_READ_FIRST_SETTINGS:
  4952. DEBUGF("recv: [IB_READ_FIRST_SETTINGS]\n");
  4953. readlen = inbound_frame_buf_read(iframe, in, last);
  4954. in += readlen;
  4955. if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
  4956. return (nghttp2_ssize)(in - first);
  4957. }
  4958. if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS ||
  4959. (iframe->sbuf.pos[4] & NGHTTP2_FLAG_ACK)) {
  4960. rv = session_call_error_callback(
  4961. session, NGHTTP2_ERR_SETTINGS_EXPECTED,
  4962. "Remote peer returned unexpected data while we expected "
  4963. "SETTINGS frame. Perhaps, peer does not support HTTP/2 "
  4964. "properly.");
  4965. if (nghttp2_is_fatal(rv)) {
  4966. return rv;
  4967. }
  4968. rv = nghttp2_session_terminate_session_with_reason(
  4969. session, NGHTTP2_PROTOCOL_ERROR, "SETTINGS expected");
  4970. if (nghttp2_is_fatal(rv)) {
  4971. return rv;
  4972. }
  4973. return (nghttp2_ssize)inlen;
  4974. }
  4975. iframe->state = NGHTTP2_IB_READ_HEAD;
  4976. /* Fall through */
  4977. case NGHTTP2_IB_READ_HEAD: {
  4978. int on_begin_frame_called = 0;
  4979. DEBUGF("recv: [IB_READ_HEAD]\n");
  4980. readlen = inbound_frame_buf_read(iframe, in, last);
  4981. in += readlen;
  4982. if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
  4983. return (nghttp2_ssize)(in - first);
  4984. }
  4985. nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos);
  4986. iframe->payloadleft = iframe->frame.hd.length;
  4987. DEBUGF("recv: payloadlen=%zu, type=%u, flags=0x%02x, stream_id=%d\n",
  4988. iframe->frame.hd.length, iframe->frame.hd.type,
  4989. iframe->frame.hd.flags, iframe->frame.hd.stream_id);
  4990. if (iframe->frame.hd.length > session->local_settings.max_frame_size) {
  4991. DEBUGF("recv: length is too large %zu > %u\n", iframe->frame.hd.length,
  4992. session->local_settings.max_frame_size);
  4993. rv = nghttp2_session_terminate_session_with_reason(
  4994. session, NGHTTP2_FRAME_SIZE_ERROR, "too large frame size");
  4995. if (nghttp2_is_fatal(rv)) {
  4996. return rv;
  4997. }
  4998. return (nghttp2_ssize)inlen;
  4999. }
  5000. switch (iframe->frame.hd.type) {
  5001. case NGHTTP2_DATA: {
  5002. DEBUGF("recv: DATA\n");
  5003. iframe->frame.hd.flags &=
  5004. (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PADDED);
  5005. /* Check stream is open. If it is not open or closing,
  5006. ignore payload. */
  5007. busy = 1;
  5008. rv = session_on_data_received_fail_fast(session);
  5009. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5010. return (nghttp2_ssize)inlen;
  5011. }
  5012. if (rv == NGHTTP2_ERR_IGN_PAYLOAD) {
  5013. DEBUGF("recv: DATA not allowed stream_id=%d\n",
  5014. iframe->frame.hd.stream_id);
  5015. iframe->state = NGHTTP2_IB_IGN_DATA;
  5016. break;
  5017. }
  5018. if (nghttp2_is_fatal(rv)) {
  5019. return rv;
  5020. }
  5021. rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
  5022. if (rv < 0) {
  5023. rv = nghttp2_session_terminate_session_with_reason(
  5024. session, NGHTTP2_PROTOCOL_ERROR,
  5025. "DATA: insufficient padding space");
  5026. if (nghttp2_is_fatal(rv)) {
  5027. return rv;
  5028. }
  5029. return (nghttp2_ssize)inlen;
  5030. }
  5031. if (rv == 1) {
  5032. iframe->state = NGHTTP2_IB_READ_PAD_DATA;
  5033. break;
  5034. }
  5035. iframe->state = NGHTTP2_IB_READ_DATA;
  5036. break;
  5037. }
  5038. case NGHTTP2_HEADERS:
  5039. DEBUGF("recv: HEADERS\n");
  5040. iframe->frame.hd.flags &=
  5041. (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
  5042. NGHTTP2_FLAG_PADDED | NGHTTP2_FLAG_PRIORITY);
  5043. rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
  5044. if (rv < 0) {
  5045. rv = nghttp2_session_terminate_session_with_reason(
  5046. session, NGHTTP2_PROTOCOL_ERROR,
  5047. "HEADERS: insufficient padding space");
  5048. if (nghttp2_is_fatal(rv)) {
  5049. return rv;
  5050. }
  5051. return (nghttp2_ssize)inlen;
  5052. }
  5053. if (rv == 1) {
  5054. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5055. break;
  5056. }
  5057. pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
  5058. if (pri_fieldlen > 0) {
  5059. if (iframe->payloadleft < pri_fieldlen) {
  5060. busy = 1;
  5061. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5062. break;
  5063. }
  5064. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5065. inbound_frame_set_mark(iframe, pri_fieldlen);
  5066. break;
  5067. }
  5068. /* Call on_begin_frame_callback here because
  5069. session_process_headers_frame() may call
  5070. on_begin_headers_callback */
  5071. rv = session_call_on_begin_frame(session, &iframe->frame.hd);
  5072. if (nghttp2_is_fatal(rv)) {
  5073. return rv;
  5074. }
  5075. on_begin_frame_called = 1;
  5076. rv = session_process_headers_frame(session);
  5077. if (nghttp2_is_fatal(rv)) {
  5078. return rv;
  5079. }
  5080. busy = 1;
  5081. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5082. return (nghttp2_ssize)inlen;
  5083. }
  5084. if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  5085. rv = nghttp2_session_add_rst_stream(
  5086. session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
  5087. if (nghttp2_is_fatal(rv)) {
  5088. return rv;
  5089. }
  5090. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5091. break;
  5092. }
  5093. if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
  5094. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5095. break;
  5096. }
  5097. iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
  5098. break;
  5099. case NGHTTP2_PRIORITY:
  5100. DEBUGF("recv: PRIORITY\n");
  5101. iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
  5102. if (iframe->payloadleft != NGHTTP2_PRIORITY_SPECLEN) {
  5103. busy = 1;
  5104. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5105. break;
  5106. }
  5107. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5108. inbound_frame_set_mark(iframe, NGHTTP2_PRIORITY_SPECLEN);
  5109. break;
  5110. case NGHTTP2_RST_STREAM:
  5111. case NGHTTP2_WINDOW_UPDATE:
  5112. #ifdef DEBUGBUILD
  5113. switch (iframe->frame.hd.type) {
  5114. case NGHTTP2_RST_STREAM:
  5115. DEBUGF("recv: RST_STREAM\n");
  5116. break;
  5117. case NGHTTP2_WINDOW_UPDATE:
  5118. DEBUGF("recv: WINDOW_UPDATE\n");
  5119. break;
  5120. }
  5121. #endif /* DEBUGBUILD */
  5122. iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
  5123. if (iframe->payloadleft != 4) {
  5124. busy = 1;
  5125. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5126. break;
  5127. }
  5128. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5129. inbound_frame_set_mark(iframe, 4);
  5130. break;
  5131. case NGHTTP2_SETTINGS:
  5132. DEBUGF("recv: SETTINGS\n");
  5133. iframe->frame.hd.flags &= NGHTTP2_FLAG_ACK;
  5134. if ((iframe->frame.hd.length % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) ||
  5135. ((iframe->frame.hd.flags & NGHTTP2_FLAG_ACK) &&
  5136. iframe->payloadleft > 0)) {
  5137. busy = 1;
  5138. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5139. break;
  5140. }
  5141. /* Check the settings flood counter early to be safe */
  5142. if (session->obq_flood_counter_ >= session->max_outbound_ack &&
  5143. !(iframe->frame.hd.flags & NGHTTP2_FLAG_ACK)) {
  5144. return NGHTTP2_ERR_FLOODED;
  5145. }
  5146. iframe->state = NGHTTP2_IB_READ_SETTINGS;
  5147. if (iframe->payloadleft) {
  5148. nghttp2_settings_entry *min_header_table_size_entry;
  5149. /* We allocate iv with additional one entry, to store the
  5150. minimum header table size. */
  5151. iframe->max_niv =
  5152. iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
  5153. if (iframe->max_niv - 1 > session->max_settings) {
  5154. rv = nghttp2_session_terminate_session_with_reason(
  5155. session, NGHTTP2_ENHANCE_YOUR_CALM,
  5156. "SETTINGS: too many setting entries");
  5157. if (nghttp2_is_fatal(rv)) {
  5158. return rv;
  5159. }
  5160. return (nghttp2_ssize)inlen;
  5161. }
  5162. iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
  5163. iframe->max_niv);
  5164. if (!iframe->iv) {
  5165. return NGHTTP2_ERR_NOMEM;
  5166. }
  5167. min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1];
  5168. min_header_table_size_entry->settings_id =
  5169. NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
  5170. min_header_table_size_entry->value = UINT32_MAX;
  5171. inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH);
  5172. break;
  5173. }
  5174. busy = 1;
  5175. inbound_frame_set_mark(iframe, 0);
  5176. break;
  5177. case NGHTTP2_PUSH_PROMISE:
  5178. DEBUGF("recv: PUSH_PROMISE\n");
  5179. iframe->frame.hd.flags &=
  5180. (NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED);
  5181. rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
  5182. if (rv < 0) {
  5183. rv = nghttp2_session_terminate_session_with_reason(
  5184. session, NGHTTP2_PROTOCOL_ERROR,
  5185. "PUSH_PROMISE: insufficient padding space");
  5186. if (nghttp2_is_fatal(rv)) {
  5187. return rv;
  5188. }
  5189. return (nghttp2_ssize)inlen;
  5190. }
  5191. if (rv == 1) {
  5192. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5193. break;
  5194. }
  5195. if (iframe->payloadleft < 4) {
  5196. busy = 1;
  5197. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5198. break;
  5199. }
  5200. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5201. inbound_frame_set_mark(iframe, 4);
  5202. break;
  5203. case NGHTTP2_PING:
  5204. DEBUGF("recv: PING\n");
  5205. iframe->frame.hd.flags &= NGHTTP2_FLAG_ACK;
  5206. if (iframe->payloadleft != 8) {
  5207. busy = 1;
  5208. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5209. break;
  5210. }
  5211. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5212. inbound_frame_set_mark(iframe, 8);
  5213. break;
  5214. case NGHTTP2_GOAWAY:
  5215. DEBUGF("recv: GOAWAY\n");
  5216. iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
  5217. if (iframe->payloadleft < 8) {
  5218. busy = 1;
  5219. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5220. break;
  5221. }
  5222. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5223. inbound_frame_set_mark(iframe, 8);
  5224. break;
  5225. case NGHTTP2_CONTINUATION:
  5226. DEBUGF("recv: unexpected CONTINUATION\n");
  5227. /* Receiving CONTINUATION in this state are subject to
  5228. connection error of type PROTOCOL_ERROR */
  5229. rv = nghttp2_session_terminate_session_with_reason(
  5230. session, NGHTTP2_PROTOCOL_ERROR, "CONTINUATION: unexpected");
  5231. if (nghttp2_is_fatal(rv)) {
  5232. return rv;
  5233. }
  5234. return (nghttp2_ssize)inlen;
  5235. default:
  5236. DEBUGF("recv: extension frame\n");
  5237. if (check_ext_type_set(session->user_recv_ext_types,
  5238. iframe->frame.hd.type)) {
  5239. if (!session->callbacks.unpack_extension_callback) {
  5240. /* Silently ignore unknown frame type. */
  5241. busy = 1;
  5242. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5243. break;
  5244. }
  5245. busy = 1;
  5246. iframe->state = NGHTTP2_IB_READ_EXTENSION_PAYLOAD;
  5247. break;
  5248. } else {
  5249. switch (iframe->frame.hd.type) {
  5250. case NGHTTP2_ALTSVC:
  5251. if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) ==
  5252. 0) {
  5253. busy = 1;
  5254. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5255. break;
  5256. }
  5257. DEBUGF("recv: ALTSVC\n");
  5258. iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
  5259. iframe->frame.ext.payload = &iframe->ext_frame_payload.altsvc;
  5260. if (session->server) {
  5261. busy = 1;
  5262. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5263. break;
  5264. }
  5265. if (iframe->payloadleft < 2) {
  5266. busy = 1;
  5267. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5268. break;
  5269. }
  5270. busy = 1;
  5271. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5272. inbound_frame_set_mark(iframe, 2);
  5273. break;
  5274. case NGHTTP2_ORIGIN:
  5275. if (!(session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN)) {
  5276. busy = 1;
  5277. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5278. break;
  5279. }
  5280. DEBUGF("recv: ORIGIN\n");
  5281. iframe->frame.ext.payload = &iframe->ext_frame_payload.origin;
  5282. if (session->server || iframe->frame.hd.stream_id ||
  5283. (iframe->frame.hd.flags & 0xf0)) {
  5284. busy = 1;
  5285. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5286. break;
  5287. }
  5288. iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
  5289. if (iframe->payloadleft) {
  5290. iframe->raw_lbuf = nghttp2_mem_malloc(mem, iframe->payloadleft);
  5291. if (iframe->raw_lbuf == NULL) {
  5292. return NGHTTP2_ERR_NOMEM;
  5293. }
  5294. nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf,
  5295. iframe->payloadleft);
  5296. } else {
  5297. busy = 1;
  5298. }
  5299. iframe->state = NGHTTP2_IB_READ_ORIGIN_PAYLOAD;
  5300. break;
  5301. case NGHTTP2_PRIORITY_UPDATE:
  5302. if ((session->builtin_recv_ext_types &
  5303. NGHTTP2_TYPEMASK_PRIORITY_UPDATE) == 0) {
  5304. busy = 1;
  5305. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5306. break;
  5307. }
  5308. DEBUGF("recv: PRIORITY_UPDATE\n");
  5309. iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
  5310. iframe->frame.ext.payload =
  5311. &iframe->ext_frame_payload.priority_update;
  5312. if (!session->server) {
  5313. rv = nghttp2_session_terminate_session_with_reason(
  5314. session, NGHTTP2_PROTOCOL_ERROR,
  5315. "PRIORITY_UPDATE is received from server");
  5316. if (nghttp2_is_fatal(rv)) {
  5317. return rv;
  5318. }
  5319. return (nghttp2_ssize)inlen;
  5320. }
  5321. if (iframe->payloadleft < 4) {
  5322. busy = 1;
  5323. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5324. break;
  5325. }
  5326. if (!session_no_rfc7540_pri_no_fallback(session) ||
  5327. iframe->payloadleft > sizeof(iframe->raw_sbuf)) {
  5328. busy = 1;
  5329. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5330. break;
  5331. }
  5332. busy = 1;
  5333. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5334. inbound_frame_set_mark(iframe, iframe->payloadleft);
  5335. break;
  5336. default:
  5337. busy = 1;
  5338. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5339. break;
  5340. }
  5341. }
  5342. }
  5343. if (!on_begin_frame_called) {
  5344. switch (iframe->state) {
  5345. case NGHTTP2_IB_IGN_HEADER_BLOCK:
  5346. case NGHTTP2_IB_IGN_PAYLOAD:
  5347. case NGHTTP2_IB_FRAME_SIZE_ERROR:
  5348. case NGHTTP2_IB_IGN_DATA:
  5349. case NGHTTP2_IB_IGN_ALL:
  5350. break;
  5351. default:
  5352. rv = session_call_on_begin_frame(session, &iframe->frame.hd);
  5353. if (nghttp2_is_fatal(rv)) {
  5354. return rv;
  5355. }
  5356. }
  5357. }
  5358. break;
  5359. }
  5360. case NGHTTP2_IB_READ_NBYTE:
  5361. DEBUGF("recv: [IB_READ_NBYTE]\n");
  5362. readlen = inbound_frame_buf_read(iframe, in, last);
  5363. in += readlen;
  5364. iframe->payloadleft -= readlen;
  5365. DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zu\n", readlen,
  5366. iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
  5367. if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
  5368. return (nghttp2_ssize)(in - first);
  5369. }
  5370. switch (iframe->frame.hd.type) {
  5371. case NGHTTP2_HEADERS:
  5372. if (iframe->padlen == 0 &&
  5373. (iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
  5374. pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
  5375. padlen = inbound_frame_compute_pad(iframe);
  5376. if (padlen < 0 ||
  5377. (size_t)padlen + pri_fieldlen > 1 + iframe->payloadleft) {
  5378. rv = nghttp2_session_terminate_session_with_reason(
  5379. session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: invalid padding");
  5380. if (nghttp2_is_fatal(rv)) {
  5381. return rv;
  5382. }
  5383. return (nghttp2_ssize)inlen;
  5384. }
  5385. iframe->frame.headers.padlen = (size_t)padlen;
  5386. if (pri_fieldlen > 0) {
  5387. if (iframe->payloadleft < pri_fieldlen) {
  5388. busy = 1;
  5389. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5390. break;
  5391. }
  5392. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5393. inbound_frame_set_mark(iframe, pri_fieldlen);
  5394. break;
  5395. } else {
  5396. /* Truncate buffers used for padding spec */
  5397. inbound_frame_set_mark(iframe, 0);
  5398. }
  5399. }
  5400. rv = session_process_headers_frame(session);
  5401. if (nghttp2_is_fatal(rv)) {
  5402. return rv;
  5403. }
  5404. busy = 1;
  5405. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5406. return (nghttp2_ssize)inlen;
  5407. }
  5408. if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  5409. rv = nghttp2_session_add_rst_stream(
  5410. session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
  5411. if (nghttp2_is_fatal(rv)) {
  5412. return rv;
  5413. }
  5414. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5415. break;
  5416. }
  5417. if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
  5418. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5419. break;
  5420. }
  5421. iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
  5422. break;
  5423. case NGHTTP2_PRIORITY:
  5424. if (!session_no_rfc7540_pri_no_fallback(session) &&
  5425. session->remote_settings.no_rfc7540_priorities != 1) {
  5426. rv = session_process_priority_frame(session);
  5427. if (nghttp2_is_fatal(rv)) {
  5428. return rv;
  5429. }
  5430. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5431. return (nghttp2_ssize)inlen;
  5432. }
  5433. }
  5434. session_inbound_frame_reset(session);
  5435. break;
  5436. case NGHTTP2_RST_STREAM:
  5437. rv = session_process_rst_stream_frame(session);
  5438. if (nghttp2_is_fatal(rv)) {
  5439. return rv;
  5440. }
  5441. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5442. return (nghttp2_ssize)inlen;
  5443. }
  5444. session_inbound_frame_reset(session);
  5445. break;
  5446. case NGHTTP2_PUSH_PROMISE:
  5447. if (iframe->padlen == 0 &&
  5448. (iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
  5449. padlen = inbound_frame_compute_pad(iframe);
  5450. if (padlen < 0 || (size_t)padlen + 4 /* promised stream id */
  5451. > 1 + iframe->payloadleft) {
  5452. rv = nghttp2_session_terminate_session_with_reason(
  5453. session, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: invalid padding");
  5454. if (nghttp2_is_fatal(rv)) {
  5455. return rv;
  5456. }
  5457. return (nghttp2_ssize)inlen;
  5458. }
  5459. iframe->frame.push_promise.padlen = (size_t)padlen;
  5460. if (iframe->payloadleft < 4) {
  5461. busy = 1;
  5462. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5463. break;
  5464. }
  5465. iframe->state = NGHTTP2_IB_READ_NBYTE;
  5466. inbound_frame_set_mark(iframe, 4);
  5467. break;
  5468. }
  5469. rv = session_process_push_promise_frame(session);
  5470. if (nghttp2_is_fatal(rv)) {
  5471. return rv;
  5472. }
  5473. busy = 1;
  5474. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5475. return (nghttp2_ssize)inlen;
  5476. }
  5477. if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  5478. rv = nghttp2_session_add_rst_stream(
  5479. session, iframe->frame.push_promise.promised_stream_id,
  5480. NGHTTP2_INTERNAL_ERROR);
  5481. if (nghttp2_is_fatal(rv)) {
  5482. return rv;
  5483. }
  5484. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5485. break;
  5486. }
  5487. if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
  5488. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5489. break;
  5490. }
  5491. iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
  5492. break;
  5493. case NGHTTP2_PING:
  5494. rv = session_process_ping_frame(session);
  5495. if (nghttp2_is_fatal(rv)) {
  5496. return rv;
  5497. }
  5498. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5499. return (nghttp2_ssize)inlen;
  5500. }
  5501. session_inbound_frame_reset(session);
  5502. break;
  5503. case NGHTTP2_GOAWAY: {
  5504. size_t debuglen;
  5505. /* 8 is Last-stream-ID + Error Code */
  5506. debuglen = iframe->frame.hd.length - 8;
  5507. if (debuglen > 0) {
  5508. iframe->raw_lbuf = nghttp2_mem_malloc(mem, debuglen);
  5509. if (iframe->raw_lbuf == NULL) {
  5510. return NGHTTP2_ERR_NOMEM;
  5511. }
  5512. nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf, debuglen);
  5513. }
  5514. busy = 1;
  5515. iframe->state = NGHTTP2_IB_READ_GOAWAY_DEBUG;
  5516. break;
  5517. }
  5518. case NGHTTP2_WINDOW_UPDATE:
  5519. rv = session_process_window_update_frame(session);
  5520. if (nghttp2_is_fatal(rv)) {
  5521. return rv;
  5522. }
  5523. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5524. return (nghttp2_ssize)inlen;
  5525. }
  5526. session_inbound_frame_reset(session);
  5527. break;
  5528. case NGHTTP2_ALTSVC: {
  5529. size_t origin_len;
  5530. origin_len = nghttp2_get_uint16(iframe->sbuf.pos);
  5531. DEBUGF("recv: origin_len=%zu\n", origin_len);
  5532. if (origin_len > iframe->payloadleft) {
  5533. busy = 1;
  5534. iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
  5535. break;
  5536. }
  5537. if (iframe->frame.hd.length > 2) {
  5538. iframe->raw_lbuf =
  5539. nghttp2_mem_malloc(mem, iframe->frame.hd.length - 2);
  5540. if (iframe->raw_lbuf == NULL) {
  5541. return NGHTTP2_ERR_NOMEM;
  5542. }
  5543. nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf,
  5544. iframe->frame.hd.length);
  5545. }
  5546. busy = 1;
  5547. iframe->state = NGHTTP2_IB_READ_ALTSVC_PAYLOAD;
  5548. break;
  5549. case NGHTTP2_PRIORITY_UPDATE:
  5550. DEBUGF("recv: prioritized_stream_id=%d\n",
  5551. nghttp2_get_uint32(iframe->sbuf.pos) & NGHTTP2_STREAM_ID_MASK);
  5552. rv = session_process_priority_update_frame(session);
  5553. if (nghttp2_is_fatal(rv)) {
  5554. return rv;
  5555. }
  5556. session_inbound_frame_reset(session);
  5557. break;
  5558. }
  5559. default:
  5560. /* This is unknown frame */
  5561. session_inbound_frame_reset(session);
  5562. break;
  5563. }
  5564. break;
  5565. case NGHTTP2_IB_READ_HEADER_BLOCK:
  5566. case NGHTTP2_IB_IGN_HEADER_BLOCK: {
  5567. nghttp2_ssize data_readlen;
  5568. size_t trail_padlen;
  5569. int final;
  5570. #ifdef DEBUGBUILD
  5571. if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
  5572. DEBUGF("recv: [IB_READ_HEADER_BLOCK]\n");
  5573. } else {
  5574. DEBUGF("recv: [IB_IGN_HEADER_BLOCK]\n");
  5575. }
  5576. #endif /* DEBUGBUILD */
  5577. readlen = inbound_frame_payload_readlen(iframe, in, last);
  5578. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  5579. iframe->payloadleft - readlen);
  5580. data_readlen = inbound_frame_effective_readlen(
  5581. iframe, iframe->payloadleft - readlen, readlen);
  5582. if (data_readlen == -1) {
  5583. /* everything is padding */
  5584. data_readlen = 0;
  5585. }
  5586. trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
  5587. final = (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) &&
  5588. iframe->payloadleft - (size_t)data_readlen == trail_padlen;
  5589. if (data_readlen > 0 || (data_readlen == 0 && final)) {
  5590. size_t hd_proclen = 0;
  5591. DEBUGF("recv: block final=%d\n", final);
  5592. rv =
  5593. inflate_header_block(session, &iframe->frame, &hd_proclen,
  5594. (uint8_t *)in, (size_t)data_readlen, final,
  5595. iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK);
  5596. if (nghttp2_is_fatal(rv)) {
  5597. return rv;
  5598. }
  5599. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5600. return (nghttp2_ssize)inlen;
  5601. }
  5602. if (rv == NGHTTP2_ERR_PAUSE) {
  5603. in += hd_proclen;
  5604. iframe->payloadleft -= hd_proclen;
  5605. return (nghttp2_ssize)(in - first);
  5606. }
  5607. if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
  5608. /* The application says no more headers. We decompress the
  5609. rest of the header block but not invoke on_header_callback
  5610. and on_frame_recv_callback. */
  5611. in += hd_proclen;
  5612. iframe->payloadleft -= hd_proclen;
  5613. /* Use promised stream ID for PUSH_PROMISE */
  5614. rv = nghttp2_session_add_rst_stream(
  5615. session,
  5616. iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE
  5617. ? iframe->frame.push_promise.promised_stream_id
  5618. : iframe->frame.hd.stream_id,
  5619. NGHTTP2_INTERNAL_ERROR);
  5620. if (nghttp2_is_fatal(rv)) {
  5621. return rv;
  5622. }
  5623. busy = 1;
  5624. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5625. break;
  5626. }
  5627. in += readlen;
  5628. iframe->payloadleft -= readlen;
  5629. if (rv == NGHTTP2_ERR_HEADER_COMP) {
  5630. /* GOAWAY is already issued */
  5631. if (iframe->payloadleft == 0) {
  5632. session_inbound_frame_reset(session);
  5633. } else {
  5634. busy = 1;
  5635. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5636. }
  5637. break;
  5638. }
  5639. } else {
  5640. in += readlen;
  5641. iframe->payloadleft -= readlen;
  5642. }
  5643. if (iframe->payloadleft) {
  5644. break;
  5645. }
  5646. if ((iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
  5647. inbound_frame_set_mark(iframe, NGHTTP2_FRAME_HDLEN);
  5648. iframe->padlen = 0;
  5649. if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
  5650. iframe->state = NGHTTP2_IB_EXPECT_CONTINUATION;
  5651. } else {
  5652. iframe->state = NGHTTP2_IB_IGN_CONTINUATION;
  5653. }
  5654. } else {
  5655. if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
  5656. rv = session_after_header_block_received(session);
  5657. if (nghttp2_is_fatal(rv)) {
  5658. return rv;
  5659. }
  5660. }
  5661. session_inbound_frame_reset(session);
  5662. session->num_continuations = 0;
  5663. }
  5664. break;
  5665. }
  5666. case NGHTTP2_IB_IGN_PAYLOAD:
  5667. DEBUGF("recv: [IB_IGN_PAYLOAD]\n");
  5668. readlen = inbound_frame_payload_readlen(iframe, in, last);
  5669. iframe->payloadleft -= readlen;
  5670. in += readlen;
  5671. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  5672. iframe->payloadleft);
  5673. if (iframe->payloadleft) {
  5674. break;
  5675. }
  5676. switch (iframe->frame.hd.type) {
  5677. case NGHTTP2_HEADERS:
  5678. case NGHTTP2_PUSH_PROMISE:
  5679. case NGHTTP2_CONTINUATION:
  5680. /* Mark inflater bad so that we won't perform further decoding */
  5681. session->hd_inflater.ctx.bad = 1;
  5682. break;
  5683. default:
  5684. break;
  5685. }
  5686. session_inbound_frame_reset(session);
  5687. break;
  5688. case NGHTTP2_IB_FRAME_SIZE_ERROR:
  5689. DEBUGF("recv: [IB_FRAME_SIZE_ERROR]\n");
  5690. rv = session_handle_frame_size_error(session);
  5691. if (nghttp2_is_fatal(rv)) {
  5692. return rv;
  5693. }
  5694. assert(iframe->state == NGHTTP2_IB_IGN_ALL);
  5695. return (nghttp2_ssize)inlen;
  5696. case NGHTTP2_IB_READ_SETTINGS:
  5697. DEBUGF("recv: [IB_READ_SETTINGS]\n");
  5698. readlen = inbound_frame_buf_read(iframe, in, last);
  5699. iframe->payloadleft -= readlen;
  5700. in += readlen;
  5701. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  5702. iframe->payloadleft);
  5703. if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
  5704. break;
  5705. }
  5706. if (readlen > 0) {
  5707. inbound_frame_set_settings_entry(iframe);
  5708. }
  5709. if (iframe->payloadleft) {
  5710. inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH);
  5711. break;
  5712. }
  5713. rv = session_process_settings_frame(session);
  5714. if (nghttp2_is_fatal(rv)) {
  5715. return rv;
  5716. }
  5717. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5718. return (nghttp2_ssize)inlen;
  5719. }
  5720. session_inbound_frame_reset(session);
  5721. break;
  5722. case NGHTTP2_IB_READ_GOAWAY_DEBUG:
  5723. DEBUGF("recv: [IB_READ_GOAWAY_DEBUG]\n");
  5724. readlen = inbound_frame_payload_readlen(iframe, in, last);
  5725. if (readlen > 0) {
  5726. iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
  5727. iframe->payloadleft -= readlen;
  5728. in += readlen;
  5729. }
  5730. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  5731. iframe->payloadleft);
  5732. if (iframe->payloadleft) {
  5733. assert(nghttp2_buf_avail(&iframe->lbuf) > 0);
  5734. break;
  5735. }
  5736. rv = session_process_goaway_frame(session);
  5737. if (nghttp2_is_fatal(rv)) {
  5738. return rv;
  5739. }
  5740. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5741. return (nghttp2_ssize)inlen;
  5742. }
  5743. session_inbound_frame_reset(session);
  5744. break;
  5745. case NGHTTP2_IB_EXPECT_CONTINUATION:
  5746. case NGHTTP2_IB_IGN_CONTINUATION:
  5747. #ifdef DEBUGBUILD
  5748. if (iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
  5749. fprintf(stderr, "recv: [IB_EXPECT_CONTINUATION]\n");
  5750. } else {
  5751. fprintf(stderr, "recv: [IB_IGN_CONTINUATION]\n");
  5752. }
  5753. #endif /* DEBUGBUILD */
  5754. if (++session->num_continuations > session->max_continuations) {
  5755. return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS;
  5756. }
  5757. readlen = inbound_frame_buf_read(iframe, in, last);
  5758. in += readlen;
  5759. if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
  5760. return (nghttp2_ssize)(in - first);
  5761. }
  5762. nghttp2_frame_unpack_frame_hd(&cont_hd, iframe->sbuf.pos);
  5763. iframe->payloadleft = cont_hd.length;
  5764. DEBUGF("recv: payloadlen=%zu, type=%u, flags=0x%02x, stream_id=%d\n",
  5765. cont_hd.length, cont_hd.type, cont_hd.flags, cont_hd.stream_id);
  5766. if (cont_hd.type != NGHTTP2_CONTINUATION ||
  5767. cont_hd.stream_id != iframe->frame.hd.stream_id) {
  5768. DEBUGF("recv: expected stream_id=%d, type=%d, but got stream_id=%d, "
  5769. "type=%u\n",
  5770. iframe->frame.hd.stream_id, NGHTTP2_CONTINUATION,
  5771. cont_hd.stream_id, cont_hd.type);
  5772. rv = nghttp2_session_terminate_session_with_reason(
  5773. session, NGHTTP2_PROTOCOL_ERROR,
  5774. "unexpected non-CONTINUATION frame or stream_id is invalid");
  5775. if (nghttp2_is_fatal(rv)) {
  5776. return rv;
  5777. }
  5778. return (nghttp2_ssize)inlen;
  5779. }
  5780. /* CONTINUATION won't bear NGHTTP2_PADDED flag */
  5781. iframe->frame.hd.flags =
  5782. (uint8_t)(iframe->frame.hd.flags |
  5783. (cont_hd.flags & NGHTTP2_FLAG_END_HEADERS));
  5784. iframe->frame.hd.length += cont_hd.length;
  5785. busy = 1;
  5786. if (iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
  5787. iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
  5788. rv = session_call_on_begin_frame(session, &cont_hd);
  5789. if (nghttp2_is_fatal(rv)) {
  5790. return rv;
  5791. }
  5792. } else {
  5793. iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
  5794. }
  5795. break;
  5796. case NGHTTP2_IB_READ_PAD_DATA:
  5797. DEBUGF("recv: [IB_READ_PAD_DATA]\n");
  5798. readlen = inbound_frame_buf_read(iframe, in, last);
  5799. in += readlen;
  5800. iframe->payloadleft -= readlen;
  5801. DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zu\n", readlen,
  5802. iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
  5803. if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
  5804. return (nghttp2_ssize)(in - first);
  5805. }
  5806. /* Pad Length field is subject to flow control */
  5807. rv = nghttp2_session_update_recv_connection_window_size(session, readlen);
  5808. if (nghttp2_is_fatal(rv)) {
  5809. return rv;
  5810. }
  5811. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5812. return (nghttp2_ssize)inlen;
  5813. }
  5814. /* Pad Length field is consumed immediately */
  5815. rv =
  5816. nghttp2_session_consume(session, iframe->frame.hd.stream_id, readlen);
  5817. if (nghttp2_is_fatal(rv)) {
  5818. return rv;
  5819. }
  5820. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5821. return (nghttp2_ssize)inlen;
  5822. }
  5823. stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
  5824. if (stream) {
  5825. rv = nghttp2_session_update_recv_stream_window_size(
  5826. session, stream, readlen,
  5827. iframe->payloadleft ||
  5828. (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
  5829. if (nghttp2_is_fatal(rv)) {
  5830. return rv;
  5831. }
  5832. }
  5833. busy = 1;
  5834. padlen = inbound_frame_compute_pad(iframe);
  5835. if (padlen < 0) {
  5836. rv = nghttp2_session_terminate_session_with_reason(
  5837. session, NGHTTP2_PROTOCOL_ERROR, "DATA: invalid padding");
  5838. if (nghttp2_is_fatal(rv)) {
  5839. return rv;
  5840. }
  5841. return (nghttp2_ssize)inlen;
  5842. }
  5843. iframe->frame.data.padlen = (size_t)padlen;
  5844. iframe->state = NGHTTP2_IB_READ_DATA;
  5845. break;
  5846. case NGHTTP2_IB_READ_DATA:
  5847. stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
  5848. if (!stream) {
  5849. busy = 1;
  5850. iframe->state = NGHTTP2_IB_IGN_DATA;
  5851. break;
  5852. }
  5853. DEBUGF("recv: [IB_READ_DATA]\n");
  5854. readlen = inbound_frame_payload_readlen(iframe, in, last);
  5855. iframe->payloadleft -= readlen;
  5856. in += readlen;
  5857. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  5858. iframe->payloadleft);
  5859. if (readlen > 0) {
  5860. nghttp2_ssize data_readlen;
  5861. rv =
  5862. nghttp2_session_update_recv_connection_window_size(session, readlen);
  5863. if (nghttp2_is_fatal(rv)) {
  5864. return rv;
  5865. }
  5866. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5867. return (nghttp2_ssize)inlen;
  5868. }
  5869. rv = nghttp2_session_update_recv_stream_window_size(
  5870. session, stream, readlen,
  5871. iframe->payloadleft ||
  5872. (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
  5873. if (nghttp2_is_fatal(rv)) {
  5874. return rv;
  5875. }
  5876. data_readlen =
  5877. inbound_frame_effective_readlen(iframe, iframe->payloadleft, readlen);
  5878. if (data_readlen == -1) {
  5879. /* everything is padding */
  5880. data_readlen = 0;
  5881. }
  5882. padlen = (nghttp2_ssize)readlen - data_readlen;
  5883. if (padlen > 0) {
  5884. /* Padding is considered as "consumed" immediately */
  5885. rv = nghttp2_session_consume(session, iframe->frame.hd.stream_id,
  5886. (size_t)padlen);
  5887. if (nghttp2_is_fatal(rv)) {
  5888. return rv;
  5889. }
  5890. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5891. return (nghttp2_ssize)inlen;
  5892. }
  5893. }
  5894. DEBUGF("recv: data_readlen=%td\n", data_readlen);
  5895. if (data_readlen > 0) {
  5896. if (session_enforce_http_messaging(session)) {
  5897. if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) {
  5898. if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
  5899. /* Consume all data for connection immediately here */
  5900. rv = session_update_connection_consumed_size(
  5901. session, (size_t)data_readlen);
  5902. if (nghttp2_is_fatal(rv)) {
  5903. return rv;
  5904. }
  5905. if (iframe->state == NGHTTP2_IB_IGN_DATA) {
  5906. return (nghttp2_ssize)inlen;
  5907. }
  5908. }
  5909. rv = nghttp2_session_add_rst_stream(
  5910. session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR);
  5911. if (nghttp2_is_fatal(rv)) {
  5912. return rv;
  5913. }
  5914. busy = 1;
  5915. iframe->state = NGHTTP2_IB_IGN_DATA;
  5916. break;
  5917. }
  5918. }
  5919. if (session->callbacks.on_data_chunk_recv_callback) {
  5920. rv = session->callbacks.on_data_chunk_recv_callback(
  5921. session, iframe->frame.hd.flags, iframe->frame.hd.stream_id,
  5922. in - readlen, (size_t)data_readlen, session->user_data);
  5923. if (rv == NGHTTP2_ERR_PAUSE) {
  5924. return (nghttp2_ssize)(in - first);
  5925. }
  5926. if (nghttp2_is_fatal(rv)) {
  5927. return NGHTTP2_ERR_CALLBACK_FAILURE;
  5928. }
  5929. }
  5930. }
  5931. }
  5932. if (iframe->payloadleft) {
  5933. break;
  5934. }
  5935. rv = session_process_data_frame(session);
  5936. if (nghttp2_is_fatal(rv)) {
  5937. return rv;
  5938. }
  5939. session_inbound_frame_reset(session);
  5940. break;
  5941. case NGHTTP2_IB_IGN_DATA:
  5942. DEBUGF("recv: [IB_IGN_DATA]\n");
  5943. readlen = inbound_frame_payload_readlen(iframe, in, last);
  5944. iframe->payloadleft -= readlen;
  5945. in += readlen;
  5946. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  5947. iframe->payloadleft);
  5948. if (readlen > 0) {
  5949. /* Update connection-level flow control window for ignored
  5950. DATA frame too */
  5951. rv =
  5952. nghttp2_session_update_recv_connection_window_size(session, readlen);
  5953. if (nghttp2_is_fatal(rv)) {
  5954. return rv;
  5955. }
  5956. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5957. return (nghttp2_ssize)inlen;
  5958. }
  5959. if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
  5960. /* Ignored DATA is considered as "consumed" immediately. */
  5961. rv = session_update_connection_consumed_size(session, readlen);
  5962. if (nghttp2_is_fatal(rv)) {
  5963. return rv;
  5964. }
  5965. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  5966. return (nghttp2_ssize)inlen;
  5967. }
  5968. }
  5969. }
  5970. if (iframe->payloadleft) {
  5971. break;
  5972. }
  5973. session_inbound_frame_reset(session);
  5974. break;
  5975. case NGHTTP2_IB_IGN_ALL:
  5976. return (nghttp2_ssize)inlen;
  5977. case NGHTTP2_IB_READ_EXTENSION_PAYLOAD:
  5978. DEBUGF("recv: [IB_READ_EXTENSION_PAYLOAD]\n");
  5979. readlen = inbound_frame_payload_readlen(iframe, in, last);
  5980. iframe->payloadleft -= readlen;
  5981. in += readlen;
  5982. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  5983. iframe->payloadleft);
  5984. if (readlen > 0) {
  5985. rv = session_call_on_extension_chunk_recv_callback(
  5986. session, in - readlen, readlen);
  5987. if (nghttp2_is_fatal(rv)) {
  5988. return rv;
  5989. }
  5990. if (rv != 0) {
  5991. busy = 1;
  5992. iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
  5993. break;
  5994. }
  5995. }
  5996. if (iframe->payloadleft > 0) {
  5997. break;
  5998. }
  5999. rv = session_process_extension_frame(session);
  6000. if (nghttp2_is_fatal(rv)) {
  6001. return rv;
  6002. }
  6003. session_inbound_frame_reset(session);
  6004. break;
  6005. case NGHTTP2_IB_READ_ALTSVC_PAYLOAD:
  6006. DEBUGF("recv: [IB_READ_ALTSVC_PAYLOAD]\n");
  6007. readlen = inbound_frame_payload_readlen(iframe, in, last);
  6008. if (readlen > 0) {
  6009. iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
  6010. iframe->payloadleft -= readlen;
  6011. in += readlen;
  6012. }
  6013. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  6014. iframe->payloadleft);
  6015. if (iframe->payloadleft) {
  6016. assert(nghttp2_buf_avail(&iframe->lbuf) > 0);
  6017. break;
  6018. }
  6019. rv = session_process_altsvc_frame(session);
  6020. if (nghttp2_is_fatal(rv)) {
  6021. return rv;
  6022. }
  6023. session_inbound_frame_reset(session);
  6024. break;
  6025. case NGHTTP2_IB_READ_ORIGIN_PAYLOAD:
  6026. DEBUGF("recv: [IB_READ_ORIGIN_PAYLOAD]\n");
  6027. readlen = inbound_frame_payload_readlen(iframe, in, last);
  6028. if (readlen > 0) {
  6029. iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
  6030. iframe->payloadleft -= readlen;
  6031. in += readlen;
  6032. }
  6033. DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
  6034. iframe->payloadleft);
  6035. if (iframe->payloadleft) {
  6036. assert(nghttp2_buf_avail(&iframe->lbuf) > 0);
  6037. break;
  6038. }
  6039. rv = session_process_origin_frame(session);
  6040. if (nghttp2_is_fatal(rv)) {
  6041. return rv;
  6042. }
  6043. if (iframe->state == NGHTTP2_IB_IGN_ALL) {
  6044. return (nghttp2_ssize)inlen;
  6045. }
  6046. session_inbound_frame_reset(session);
  6047. break;
  6048. }
  6049. if (!busy && in == last) {
  6050. break;
  6051. }
  6052. busy = 0;
  6053. }
  6054. assert(in == last);
  6055. return (nghttp2_ssize)(in - first);
  6056. }
  6057. int nghttp2_session_recv(nghttp2_session *session) {
  6058. uint8_t buf[NGHTTP2_INBOUND_BUFFER_LENGTH];
  6059. while (1) {
  6060. nghttp2_ssize readlen;
  6061. readlen = session_recv(session, buf, sizeof(buf));
  6062. if (readlen > 0) {
  6063. nghttp2_ssize proclen =
  6064. nghttp2_session_mem_recv2(session, buf, (size_t)readlen);
  6065. if (proclen < 0) {
  6066. return (int)proclen;
  6067. }
  6068. assert(proclen == readlen);
  6069. } else if (readlen == 0 || readlen == NGHTTP2_ERR_WOULDBLOCK) {
  6070. return 0;
  6071. } else if (readlen == NGHTTP2_ERR_EOF) {
  6072. return NGHTTP2_ERR_EOF;
  6073. } else if (readlen < 0) {
  6074. return NGHTTP2_ERR_CALLBACK_FAILURE;
  6075. }
  6076. }
  6077. }
  6078. /*
  6079. * Returns the number of active streams, which includes streams in
  6080. * reserved state.
  6081. */
  6082. static size_t session_get_num_active_streams(nghttp2_session *session) {
  6083. return nghttp2_map_size(&session->streams) - session->num_closed_streams -
  6084. session->num_idle_streams;
  6085. }
  6086. int nghttp2_session_want_read(nghttp2_session *session) {
  6087. size_t num_active_streams;
  6088. /* If this flag is set, we don't want to read. The application
  6089. should drop the connection. */
  6090. if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) {
  6091. return 0;
  6092. }
  6093. num_active_streams = session_get_num_active_streams(session);
  6094. /* Unless termination GOAWAY is sent or received, we always want to
  6095. read incoming frames. */
  6096. if (num_active_streams > 0) {
  6097. return 1;
  6098. }
  6099. /* If there is no active streams and GOAWAY has been sent or
  6100. received, we are done with this session. */
  6101. return (session->goaway_flags &
  6102. (NGHTTP2_GOAWAY_SENT | NGHTTP2_GOAWAY_RECV)) == 0;
  6103. }
  6104. int nghttp2_session_want_write(nghttp2_session *session) {
  6105. /* If these flag is set, we don't want to write any data. The
  6106. application should drop the connection. */
  6107. if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) {
  6108. return 0;
  6109. }
  6110. /*
  6111. * Unless termination GOAWAY is sent or received, we want to write
  6112. * frames if there is pending ones. If pending frame is request/push
  6113. * response HEADERS and concurrent stream limit is reached, we don't
  6114. * want to write them.
  6115. */
  6116. return session->aob.item || nghttp2_outbound_queue_top(&session->ob_urgent) ||
  6117. nghttp2_outbound_queue_top(&session->ob_reg) ||
  6118. ((!nghttp2_pq_empty(&session->root.obq) ||
  6119. !session_sched_empty(session)) &&
  6120. session->remote_window_size > 0) ||
  6121. (nghttp2_outbound_queue_top(&session->ob_syn) &&
  6122. !session_is_outgoing_concurrent_streams_max(session));
  6123. }
  6124. int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags,
  6125. const uint8_t *opaque_data) {
  6126. int rv;
  6127. nghttp2_outbound_item *item;
  6128. nghttp2_frame *frame;
  6129. nghttp2_mem *mem;
  6130. mem = &session->mem;
  6131. if ((flags & NGHTTP2_FLAG_ACK) &&
  6132. session->obq_flood_counter_ >= session->max_outbound_ack) {
  6133. return NGHTTP2_ERR_FLOODED;
  6134. }
  6135. item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  6136. if (item == NULL) {
  6137. return NGHTTP2_ERR_NOMEM;
  6138. }
  6139. nghttp2_outbound_item_init(item);
  6140. frame = &item->frame;
  6141. nghttp2_frame_ping_init(&frame->ping, flags, opaque_data);
  6142. rv = nghttp2_session_add_item(session, item);
  6143. if (rv != 0) {
  6144. nghttp2_frame_ping_free(&frame->ping);
  6145. nghttp2_mem_free(mem, item);
  6146. return rv;
  6147. }
  6148. if (flags & NGHTTP2_FLAG_ACK) {
  6149. ++session->obq_flood_counter_;
  6150. }
  6151. return 0;
  6152. }
  6153. int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id,
  6154. uint32_t error_code, const uint8_t *opaque_data,
  6155. size_t opaque_data_len, uint8_t aux_flags) {
  6156. int rv;
  6157. nghttp2_outbound_item *item;
  6158. nghttp2_frame *frame;
  6159. uint8_t *opaque_data_copy = NULL;
  6160. nghttp2_goaway_aux_data *aux_data;
  6161. nghttp2_mem *mem;
  6162. mem = &session->mem;
  6163. if (nghttp2_session_is_my_stream_id(session, last_stream_id)) {
  6164. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6165. }
  6166. if (opaque_data_len) {
  6167. if (opaque_data_len + 8 > NGHTTP2_MAX_PAYLOADLEN) {
  6168. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6169. }
  6170. opaque_data_copy = nghttp2_mem_malloc(mem, opaque_data_len);
  6171. if (opaque_data_copy == NULL) {
  6172. return NGHTTP2_ERR_NOMEM;
  6173. }
  6174. memcpy(opaque_data_copy, opaque_data, opaque_data_len);
  6175. }
  6176. item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  6177. if (item == NULL) {
  6178. nghttp2_mem_free(mem, opaque_data_copy);
  6179. return NGHTTP2_ERR_NOMEM;
  6180. }
  6181. nghttp2_outbound_item_init(item);
  6182. frame = &item->frame;
  6183. /* last_stream_id must not be increased from the value previously
  6184. sent */
  6185. last_stream_id =
  6186. nghttp2_min_int32(last_stream_id, session->local_last_stream_id);
  6187. nghttp2_frame_goaway_init(&frame->goaway, last_stream_id, error_code,
  6188. opaque_data_copy, opaque_data_len);
  6189. aux_data = &item->aux_data.goaway;
  6190. aux_data->flags = aux_flags;
  6191. rv = nghttp2_session_add_item(session, item);
  6192. if (rv != 0) {
  6193. nghttp2_frame_goaway_free(&frame->goaway, mem);
  6194. nghttp2_mem_free(mem, item);
  6195. return rv;
  6196. }
  6197. session->goaway_flags |= NGHTTP2_GOAWAY_SUBMITTED;
  6198. return 0;
  6199. }
  6200. int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
  6201. int32_t stream_id,
  6202. int32_t window_size_increment) {
  6203. int rv;
  6204. nghttp2_outbound_item *item;
  6205. nghttp2_frame *frame;
  6206. nghttp2_mem *mem;
  6207. mem = &session->mem;
  6208. item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  6209. if (item == NULL) {
  6210. return NGHTTP2_ERR_NOMEM;
  6211. }
  6212. nghttp2_outbound_item_init(item);
  6213. frame = &item->frame;
  6214. nghttp2_frame_window_update_init(&frame->window_update, flags, stream_id,
  6215. window_size_increment);
  6216. rv = nghttp2_session_add_item(session, item);
  6217. if (rv != 0) {
  6218. nghttp2_frame_window_update_free(&frame->window_update);
  6219. nghttp2_mem_free(mem, item);
  6220. return rv;
  6221. }
  6222. return 0;
  6223. }
  6224. static void
  6225. session_append_inflight_settings(nghttp2_session *session,
  6226. nghttp2_inflight_settings *settings) {
  6227. nghttp2_inflight_settings **i;
  6228. for (i = &session->inflight_settings_head; *i; i = &(*i)->next)
  6229. ;
  6230. *i = settings;
  6231. }
  6232. int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
  6233. const nghttp2_settings_entry *iv, size_t niv) {
  6234. nghttp2_outbound_item *item;
  6235. nghttp2_frame *frame;
  6236. nghttp2_settings_entry *iv_copy;
  6237. size_t i;
  6238. int rv;
  6239. nghttp2_mem *mem;
  6240. nghttp2_inflight_settings *inflight_settings = NULL;
  6241. uint8_t no_rfc7540_pri = session->pending_no_rfc7540_priorities;
  6242. mem = &session->mem;
  6243. if (flags & NGHTTP2_FLAG_ACK) {
  6244. if (niv != 0) {
  6245. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6246. }
  6247. if (session->obq_flood_counter_ >= session->max_outbound_ack) {
  6248. return NGHTTP2_ERR_FLOODED;
  6249. }
  6250. }
  6251. if (!nghttp2_iv_check(iv, niv)) {
  6252. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6253. }
  6254. for (i = 0; i < niv; ++i) {
  6255. if (iv[i].settings_id != NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES) {
  6256. continue;
  6257. }
  6258. if (no_rfc7540_pri == UINT8_MAX) {
  6259. no_rfc7540_pri = (uint8_t)iv[i].value;
  6260. continue;
  6261. }
  6262. if (iv[i].value != (uint32_t)no_rfc7540_pri) {
  6263. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6264. }
  6265. }
  6266. item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
  6267. if (item == NULL) {
  6268. return NGHTTP2_ERR_NOMEM;
  6269. }
  6270. if (niv > 0) {
  6271. iv_copy = nghttp2_frame_iv_copy(iv, niv, mem);
  6272. if (iv_copy == NULL) {
  6273. nghttp2_mem_free(mem, item);
  6274. return NGHTTP2_ERR_NOMEM;
  6275. }
  6276. } else {
  6277. iv_copy = NULL;
  6278. }
  6279. if ((flags & NGHTTP2_FLAG_ACK) == 0) {
  6280. rv = inflight_settings_new(&inflight_settings, iv, niv, mem);
  6281. if (rv != 0) {
  6282. assert(nghttp2_is_fatal(rv));
  6283. nghttp2_mem_free(mem, iv_copy);
  6284. nghttp2_mem_free(mem, item);
  6285. return rv;
  6286. }
  6287. }
  6288. nghttp2_outbound_item_init(item);
  6289. frame = &item->frame;
  6290. nghttp2_frame_settings_init(&frame->settings, flags, iv_copy, niv);
  6291. rv = nghttp2_session_add_item(session, item);
  6292. if (rv != 0) {
  6293. /* The only expected error is fatal one */
  6294. assert(nghttp2_is_fatal(rv));
  6295. inflight_settings_del(inflight_settings, mem);
  6296. nghttp2_frame_settings_free(&frame->settings, mem);
  6297. nghttp2_mem_free(mem, item);
  6298. return rv;
  6299. }
  6300. if (flags & NGHTTP2_FLAG_ACK) {
  6301. ++session->obq_flood_counter_;
  6302. } else {
  6303. session_append_inflight_settings(session, inflight_settings);
  6304. }
  6305. /* Extract NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS and ENABLE_PUSH
  6306. here. We use it to refuse the incoming stream and PUSH_PROMISE
  6307. with RST_STREAM. */
  6308. for (i = niv; i > 0; --i) {
  6309. if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) {
  6310. session->pending_local_max_concurrent_stream = iv[i - 1].value;
  6311. break;
  6312. }
  6313. }
  6314. for (i = niv; i > 0; --i) {
  6315. if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_ENABLE_PUSH) {
  6316. session->pending_enable_push = (uint8_t)iv[i - 1].value;
  6317. break;
  6318. }
  6319. }
  6320. for (i = niv; i > 0; --i) {
  6321. if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL) {
  6322. session->pending_enable_connect_protocol = (uint8_t)iv[i - 1].value;
  6323. break;
  6324. }
  6325. }
  6326. if (no_rfc7540_pri == UINT8_MAX) {
  6327. session->pending_no_rfc7540_priorities = 0;
  6328. } else {
  6329. session->pending_no_rfc7540_priorities = no_rfc7540_pri;
  6330. }
  6331. return 0;
  6332. }
  6333. int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
  6334. size_t datamax, nghttp2_frame *frame,
  6335. nghttp2_data_aux_data *aux_data,
  6336. nghttp2_stream *stream) {
  6337. int rv;
  6338. uint32_t data_flags;
  6339. nghttp2_ssize payloadlen;
  6340. nghttp2_ssize padded_payloadlen;
  6341. nghttp2_buf *buf;
  6342. size_t max_payloadlen;
  6343. assert(bufs->head == bufs->cur);
  6344. buf = &bufs->cur->buf;
  6345. if (session->callbacks.read_length_callback2 ||
  6346. session->callbacks.read_length_callback) {
  6347. if (session->callbacks.read_length_callback2) {
  6348. payloadlen = session->callbacks.read_length_callback2(
  6349. session, frame->hd.type, stream->stream_id, session->remote_window_size,
  6350. stream->remote_window_size, session->remote_settings.max_frame_size,
  6351. session->user_data);
  6352. } else {
  6353. payloadlen = (nghttp2_ssize)session->callbacks.read_length_callback(
  6354. session, frame->hd.type, stream->stream_id, session->remote_window_size,
  6355. stream->remote_window_size, session->remote_settings.max_frame_size,
  6356. session->user_data);
  6357. }
  6358. DEBUGF("send: read_length_callback=%td\n", payloadlen);
  6359. payloadlen =
  6360. nghttp2_session_enforce_flow_control_limits(session, stream, payloadlen);
  6361. DEBUGF("send: read_length_callback after flow control=%td\n", payloadlen);
  6362. if (payloadlen <= 0) {
  6363. return NGHTTP2_ERR_CALLBACK_FAILURE;
  6364. }
  6365. if ((size_t)payloadlen > nghttp2_buf_avail(buf)) {
  6366. /* Resize the current buffer(s). The reason why we do +1 for
  6367. buffer size is for possible padding field. */
  6368. rv = nghttp2_bufs_realloc(&session->aob.framebufs,
  6369. (size_t)(NGHTTP2_FRAME_HDLEN + 1 + payloadlen));
  6370. if (rv != 0) {
  6371. DEBUGF("send: realloc buffer failed rv=%d", rv);
  6372. /* If reallocation failed, old buffers are still in tact. So
  6373. use safe limit. */
  6374. payloadlen = (nghttp2_ssize)datamax;
  6375. DEBUGF("send: use safe limit payloadlen=%td", payloadlen);
  6376. } else {
  6377. assert(&session->aob.framebufs == bufs);
  6378. buf = &bufs->cur->buf;
  6379. }
  6380. }
  6381. datamax = (size_t)payloadlen;
  6382. }
  6383. /* Current max DATA length is less then buffer chunk size */
  6384. assert(nghttp2_buf_avail(buf) >= datamax);
  6385. data_flags = NGHTTP2_DATA_FLAG_NONE;
  6386. switch (aux_data->dpw.version) {
  6387. case NGHTTP2_DATA_PROVIDER_V1:
  6388. payloadlen = (nghttp2_ssize)aux_data->dpw.data_prd.v1.read_callback(
  6389. session, frame->hd.stream_id, buf->pos, datamax, &data_flags,
  6390. &aux_data->dpw.data_prd.source, session->user_data);
  6391. break;
  6392. case NGHTTP2_DATA_PROVIDER_V2:
  6393. payloadlen = aux_data->dpw.data_prd.v2.read_callback(
  6394. session, frame->hd.stream_id, buf->pos, datamax, &data_flags,
  6395. &aux_data->dpw.data_prd.source, session->user_data);
  6396. break;
  6397. default:
  6398. assert(0);
  6399. abort();
  6400. }
  6401. if (payloadlen == NGHTTP2_ERR_DEFERRED ||
  6402. payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ||
  6403. payloadlen == NGHTTP2_ERR_PAUSE) {
  6404. DEBUGF("send: DATA postponed due to %s\n",
  6405. nghttp2_strerror((int)payloadlen));
  6406. return (int)payloadlen;
  6407. }
  6408. if (payloadlen < 0 || datamax < (size_t)payloadlen) {
  6409. /* This is the error code when callback is failed. */
  6410. return NGHTTP2_ERR_CALLBACK_FAILURE;
  6411. }
  6412. buf->last = buf->pos + payloadlen;
  6413. buf->pos -= NGHTTP2_FRAME_HDLEN;
  6414. /* Clear flags, because this may contain previous flags of previous
  6415. DATA */
  6416. frame->hd.flags = NGHTTP2_FLAG_NONE;
  6417. if (data_flags & NGHTTP2_DATA_FLAG_EOF) {
  6418. aux_data->eof = 1;
  6419. /* If NGHTTP2_DATA_FLAG_NO_END_STREAM is set, don't set
  6420. NGHTTP2_FLAG_END_STREAM */
  6421. if ((aux_data->flags & NGHTTP2_FLAG_END_STREAM) &&
  6422. (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM) == 0) {
  6423. frame->hd.flags |= NGHTTP2_FLAG_END_STREAM;
  6424. }
  6425. }
  6426. if (data_flags & NGHTTP2_DATA_FLAG_NO_COPY) {
  6427. if (session->callbacks.send_data_callback == NULL) {
  6428. DEBUGF("NGHTTP2_DATA_FLAG_NO_COPY requires send_data_callback set\n");
  6429. return NGHTTP2_ERR_CALLBACK_FAILURE;
  6430. }
  6431. aux_data->no_copy = 1;
  6432. }
  6433. frame->hd.length = (size_t)payloadlen;
  6434. frame->data.padlen = 0;
  6435. max_payloadlen =
  6436. nghttp2_min_size(datamax, frame->hd.length + NGHTTP2_MAX_PADLEN);
  6437. padded_payloadlen =
  6438. session_call_select_padding(session, frame, max_payloadlen);
  6439. if (nghttp2_is_fatal((int)padded_payloadlen)) {
  6440. return (int)padded_payloadlen;
  6441. }
  6442. frame->data.padlen = (size_t)(padded_payloadlen - payloadlen);
  6443. nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
  6444. nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen,
  6445. aux_data->no_copy);
  6446. session_reschedule_stream(session, stream);
  6447. if (frame->hd.length == 0 && (data_flags & NGHTTP2_DATA_FLAG_EOF) &&
  6448. (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM)) {
  6449. /* DATA payload length is 0, and DATA frame does not bear
  6450. END_STREAM. In this case, there is no point to send 0 length
  6451. DATA frame. */
  6452. return NGHTTP2_ERR_CANCEL;
  6453. }
  6454. return 0;
  6455. }
  6456. void *nghttp2_session_get_stream_user_data(nghttp2_session *session,
  6457. int32_t stream_id) {
  6458. nghttp2_stream *stream;
  6459. stream = nghttp2_session_get_stream(session, stream_id);
  6460. if (stream) {
  6461. return stream->stream_user_data;
  6462. } else {
  6463. return NULL;
  6464. }
  6465. }
  6466. int nghttp2_session_set_stream_user_data(nghttp2_session *session,
  6467. int32_t stream_id,
  6468. void *stream_user_data) {
  6469. nghttp2_stream *stream;
  6470. nghttp2_frame *frame;
  6471. nghttp2_outbound_item *item;
  6472. stream = nghttp2_session_get_stream(session, stream_id);
  6473. if (stream) {
  6474. stream->stream_user_data = stream_user_data;
  6475. return 0;
  6476. }
  6477. if (session->server || !nghttp2_session_is_my_stream_id(session, stream_id) ||
  6478. !nghttp2_outbound_queue_top(&session->ob_syn)) {
  6479. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6480. }
  6481. frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame;
  6482. assert(frame->hd.type == NGHTTP2_HEADERS);
  6483. if (frame->hd.stream_id > stream_id ||
  6484. (uint32_t)stream_id >= session->next_stream_id) {
  6485. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6486. }
  6487. for (item = session->ob_syn.head; item; item = item->qnext) {
  6488. if (item->frame.hd.stream_id < stream_id) {
  6489. continue;
  6490. }
  6491. if (item->frame.hd.stream_id > stream_id) {
  6492. break;
  6493. }
  6494. item->aux_data.headers.stream_user_data = stream_user_data;
  6495. return 0;
  6496. }
  6497. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6498. }
  6499. int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) {
  6500. int rv;
  6501. nghttp2_stream *stream;
  6502. stream = nghttp2_session_get_stream(session, stream_id);
  6503. if (stream == NULL || !nghttp2_stream_check_deferred_item(stream)) {
  6504. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6505. }
  6506. rv = session_resume_deferred_stream_item(session, stream,
  6507. NGHTTP2_STREAM_FLAG_DEFERRED_USER);
  6508. if (nghttp2_is_fatal(rv)) {
  6509. return rv;
  6510. }
  6511. return 0;
  6512. }
  6513. size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session) {
  6514. return nghttp2_outbound_queue_size(&session->ob_urgent) +
  6515. nghttp2_outbound_queue_size(&session->ob_reg) +
  6516. nghttp2_outbound_queue_size(&session->ob_syn);
  6517. /* TODO account for item attached to stream */
  6518. }
  6519. int32_t
  6520. nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session,
  6521. int32_t stream_id) {
  6522. nghttp2_stream *stream;
  6523. stream = nghttp2_session_get_stream(session, stream_id);
  6524. if (stream == NULL) {
  6525. return -1;
  6526. }
  6527. return stream->recv_window_size < 0 ? 0 : stream->recv_window_size;
  6528. }
  6529. int32_t
  6530. nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session,
  6531. int32_t stream_id) {
  6532. nghttp2_stream *stream;
  6533. stream = nghttp2_session_get_stream(session, stream_id);
  6534. if (stream == NULL) {
  6535. return -1;
  6536. }
  6537. return stream->local_window_size;
  6538. }
  6539. int32_t nghttp2_session_get_stream_local_window_size(nghttp2_session *session,
  6540. int32_t stream_id) {
  6541. nghttp2_stream *stream;
  6542. int32_t size;
  6543. stream = nghttp2_session_get_stream(session, stream_id);
  6544. if (stream == NULL) {
  6545. return -1;
  6546. }
  6547. size = stream->local_window_size - stream->recv_window_size;
  6548. /* size could be negative if local endpoint reduced
  6549. SETTINGS_INITIAL_WINDOW_SIZE */
  6550. if (size < 0) {
  6551. return 0;
  6552. }
  6553. return size;
  6554. }
  6555. int32_t
  6556. nghttp2_session_get_effective_recv_data_length(nghttp2_session *session) {
  6557. return session->recv_window_size < 0 ? 0 : session->recv_window_size;
  6558. }
  6559. int32_t
  6560. nghttp2_session_get_effective_local_window_size(nghttp2_session *session) {
  6561. return session->local_window_size;
  6562. }
  6563. int32_t nghttp2_session_get_local_window_size(nghttp2_session *session) {
  6564. return session->local_window_size - session->recv_window_size;
  6565. }
  6566. int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session *session,
  6567. int32_t stream_id) {
  6568. nghttp2_stream *stream;
  6569. stream = nghttp2_session_get_stream(session, stream_id);
  6570. if (stream == NULL) {
  6571. return -1;
  6572. }
  6573. /* stream->remote_window_size can be negative when
  6574. SETTINGS_INITIAL_WINDOW_SIZE is changed. */
  6575. return nghttp2_max_int32(0, stream->remote_window_size);
  6576. }
  6577. int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session) {
  6578. return session->remote_window_size;
  6579. }
  6580. uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session,
  6581. nghttp2_settings_id id) {
  6582. switch (id) {
  6583. case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
  6584. return session->remote_settings.header_table_size;
  6585. case NGHTTP2_SETTINGS_ENABLE_PUSH:
  6586. return session->remote_settings.enable_push;
  6587. case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
  6588. return session->remote_settings.max_concurrent_streams;
  6589. case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
  6590. return session->remote_settings.initial_window_size;
  6591. case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
  6592. return session->remote_settings.max_frame_size;
  6593. case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
  6594. return session->remote_settings.max_header_list_size;
  6595. case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
  6596. return session->remote_settings.enable_connect_protocol;
  6597. case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
  6598. return session->remote_settings.no_rfc7540_priorities;
  6599. }
  6600. assert(0);
  6601. abort(); /* if NDEBUG is set */
  6602. }
  6603. uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
  6604. nghttp2_settings_id id) {
  6605. switch (id) {
  6606. case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
  6607. return session->local_settings.header_table_size;
  6608. case NGHTTP2_SETTINGS_ENABLE_PUSH:
  6609. return session->local_settings.enable_push;
  6610. case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
  6611. return session->local_settings.max_concurrent_streams;
  6612. case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
  6613. return session->local_settings.initial_window_size;
  6614. case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
  6615. return session->local_settings.max_frame_size;
  6616. case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
  6617. return session->local_settings.max_header_list_size;
  6618. case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
  6619. return session->local_settings.enable_connect_protocol;
  6620. case NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES:
  6621. return session->local_settings.no_rfc7540_priorities;
  6622. }
  6623. assert(0);
  6624. abort(); /* if NDEBUG is set */
  6625. }
  6626. static int nghttp2_session_upgrade_internal(nghttp2_session *session,
  6627. const uint8_t *settings_payload,
  6628. size_t settings_payloadlen,
  6629. void *stream_user_data) {
  6630. nghttp2_stream *stream;
  6631. nghttp2_frame frame;
  6632. nghttp2_settings_entry *iv;
  6633. size_t niv;
  6634. int rv;
  6635. nghttp2_priority_spec pri_spec;
  6636. nghttp2_mem *mem;
  6637. mem = &session->mem;
  6638. if ((!session->server && session->next_stream_id != 1) ||
  6639. (session->server && session->last_recv_stream_id >= 1)) {
  6640. return NGHTTP2_ERR_PROTO;
  6641. }
  6642. if (settings_payloadlen % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
  6643. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6644. }
  6645. /* SETTINGS frame contains too many settings */
  6646. if (settings_payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH >
  6647. session->max_settings) {
  6648. return NGHTTP2_ERR_TOO_MANY_SETTINGS;
  6649. }
  6650. rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload,
  6651. settings_payloadlen, mem);
  6652. if (rv != 0) {
  6653. return rv;
  6654. }
  6655. if (session->server) {
  6656. nghttp2_frame_hd_init(&frame.hd, settings_payloadlen, NGHTTP2_SETTINGS,
  6657. NGHTTP2_FLAG_NONE, 0);
  6658. frame.settings.iv = iv;
  6659. frame.settings.niv = niv;
  6660. rv = nghttp2_session_on_settings_received(session, &frame, 1 /* No ACK */);
  6661. } else {
  6662. rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
  6663. }
  6664. nghttp2_mem_free(mem, iv);
  6665. if (rv != 0) {
  6666. return rv;
  6667. }
  6668. nghttp2_priority_spec_default_init(&pri_spec);
  6669. stream = nghttp2_session_open_stream(
  6670. session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_OPENING,
  6671. session->server ? NULL : stream_user_data);
  6672. if (stream == NULL) {
  6673. return NGHTTP2_ERR_NOMEM;
  6674. }
  6675. /* We don't call nghttp2_session_adjust_closed_stream(), since this
  6676. should be the first stream open. */
  6677. if (session->server) {
  6678. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
  6679. session->last_recv_stream_id = 1;
  6680. session->last_proc_stream_id = 1;
  6681. } else {
  6682. nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
  6683. session->last_sent_stream_id = 1;
  6684. session->next_stream_id += 2;
  6685. }
  6686. return 0;
  6687. }
  6688. int nghttp2_session_upgrade(nghttp2_session *session,
  6689. const uint8_t *settings_payload,
  6690. size_t settings_payloadlen,
  6691. void *stream_user_data) {
  6692. int rv;
  6693. nghttp2_stream *stream;
  6694. rv = nghttp2_session_upgrade_internal(session, settings_payload,
  6695. settings_payloadlen, stream_user_data);
  6696. if (rv != 0) {
  6697. return rv;
  6698. }
  6699. stream = nghttp2_session_get_stream(session, 1);
  6700. assert(stream);
  6701. /* We have no information about request header fields when Upgrade
  6702. was happened. So we don't know the request method here. If
  6703. request method is HEAD, we have a trouble because we may have
  6704. nonzero content-length header field in response headers, and we
  6705. will going to check it against the actual DATA frames, but we may
  6706. get mismatch because HEAD response body must be empty. Because
  6707. of this reason, nghttp2_session_upgrade() was deprecated in favor
  6708. of nghttp2_session_upgrade2(), which has |head_request| parameter
  6709. to indicate that request method is HEAD or not. */
  6710. stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND;
  6711. return 0;
  6712. }
  6713. int nghttp2_session_upgrade2(nghttp2_session *session,
  6714. const uint8_t *settings_payload,
  6715. size_t settings_payloadlen, int head_request,
  6716. void *stream_user_data) {
  6717. int rv;
  6718. nghttp2_stream *stream;
  6719. rv = nghttp2_session_upgrade_internal(session, settings_payload,
  6720. settings_payloadlen, stream_user_data);
  6721. if (rv != 0) {
  6722. return rv;
  6723. }
  6724. stream = nghttp2_session_get_stream(session, 1);
  6725. assert(stream);
  6726. if (head_request) {
  6727. stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
  6728. }
  6729. return 0;
  6730. }
  6731. int nghttp2_session_get_stream_local_close(nghttp2_session *session,
  6732. int32_t stream_id) {
  6733. nghttp2_stream *stream;
  6734. stream = nghttp2_session_get_stream(session, stream_id);
  6735. if (!stream) {
  6736. return -1;
  6737. }
  6738. return (stream->shut_flags & NGHTTP2_SHUT_WR) != 0;
  6739. }
  6740. int nghttp2_session_get_stream_remote_close(nghttp2_session *session,
  6741. int32_t stream_id) {
  6742. nghttp2_stream *stream;
  6743. stream = nghttp2_session_get_stream(session, stream_id);
  6744. if (!stream) {
  6745. return -1;
  6746. }
  6747. return (stream->shut_flags & NGHTTP2_SHUT_RD) != 0;
  6748. }
  6749. int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id,
  6750. size_t size) {
  6751. int rv;
  6752. nghttp2_stream *stream;
  6753. if (stream_id == 0) {
  6754. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6755. }
  6756. if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
  6757. return NGHTTP2_ERR_INVALID_STATE;
  6758. }
  6759. rv = session_update_connection_consumed_size(session, size);
  6760. if (nghttp2_is_fatal(rv)) {
  6761. return rv;
  6762. }
  6763. stream = nghttp2_session_get_stream(session, stream_id);
  6764. if (!stream) {
  6765. return 0;
  6766. }
  6767. rv = session_update_stream_consumed_size(session, stream, size);
  6768. if (nghttp2_is_fatal(rv)) {
  6769. return rv;
  6770. }
  6771. return 0;
  6772. }
  6773. int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) {
  6774. int rv;
  6775. if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
  6776. return NGHTTP2_ERR_INVALID_STATE;
  6777. }
  6778. rv = session_update_connection_consumed_size(session, size);
  6779. if (nghttp2_is_fatal(rv)) {
  6780. return rv;
  6781. }
  6782. return 0;
  6783. }
  6784. int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id,
  6785. size_t size) {
  6786. int rv;
  6787. nghttp2_stream *stream;
  6788. if (stream_id == 0) {
  6789. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6790. }
  6791. if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
  6792. return NGHTTP2_ERR_INVALID_STATE;
  6793. }
  6794. stream = nghttp2_session_get_stream(session, stream_id);
  6795. if (!stream) {
  6796. return 0;
  6797. }
  6798. rv = session_update_stream_consumed_size(session, stream, size);
  6799. if (nghttp2_is_fatal(rv)) {
  6800. return rv;
  6801. }
  6802. return 0;
  6803. }
  6804. int nghttp2_session_set_next_stream_id(nghttp2_session *session,
  6805. int32_t next_stream_id) {
  6806. if (next_stream_id <= 0 ||
  6807. session->next_stream_id > (uint32_t)next_stream_id) {
  6808. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6809. }
  6810. if (session->server) {
  6811. if (next_stream_id % 2) {
  6812. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6813. }
  6814. } else if (next_stream_id % 2 == 0) {
  6815. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6816. }
  6817. session->next_stream_id = (uint32_t)next_stream_id;
  6818. return 0;
  6819. }
  6820. uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) {
  6821. return session->next_stream_id;
  6822. }
  6823. int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) {
  6824. return session->last_proc_stream_id;
  6825. }
  6826. nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session,
  6827. int32_t stream_id) {
  6828. if (stream_id == 0) {
  6829. return &session->root;
  6830. }
  6831. return nghttp2_session_get_stream_raw(session, stream_id);
  6832. }
  6833. nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) {
  6834. return &session->root;
  6835. }
  6836. int nghttp2_session_check_server_session(nghttp2_session *session) {
  6837. return session->server;
  6838. }
  6839. int nghttp2_session_change_stream_priority(
  6840. nghttp2_session *session, int32_t stream_id,
  6841. const nghttp2_priority_spec *pri_spec) {
  6842. int rv;
  6843. nghttp2_stream *stream;
  6844. nghttp2_priority_spec pri_spec_copy;
  6845. if (session->pending_no_rfc7540_priorities == 1) {
  6846. return 0;
  6847. }
  6848. if (stream_id == 0 || stream_id == pri_spec->stream_id) {
  6849. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6850. }
  6851. stream = nghttp2_session_get_stream_raw(session, stream_id);
  6852. if (!stream) {
  6853. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6854. }
  6855. pri_spec_copy = *pri_spec;
  6856. nghttp2_priority_spec_normalize_weight(&pri_spec_copy);
  6857. rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec_copy);
  6858. if (nghttp2_is_fatal(rv)) {
  6859. return rv;
  6860. }
  6861. /* We don't intentionally call nghttp2_session_adjust_idle_stream()
  6862. so that idle stream created by this function, and existing ones
  6863. are kept for application. We will adjust number of idle stream
  6864. in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is
  6865. called. */
  6866. return 0;
  6867. }
  6868. int nghttp2_session_create_idle_stream(nghttp2_session *session,
  6869. int32_t stream_id,
  6870. const nghttp2_priority_spec *pri_spec) {
  6871. nghttp2_stream *stream;
  6872. nghttp2_priority_spec pri_spec_copy;
  6873. if (session->pending_no_rfc7540_priorities == 1) {
  6874. return 0;
  6875. }
  6876. if (stream_id == 0 || stream_id == pri_spec->stream_id ||
  6877. !session_detect_idle_stream(session, stream_id)) {
  6878. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6879. }
  6880. stream = nghttp2_session_get_stream_raw(session, stream_id);
  6881. if (stream) {
  6882. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6883. }
  6884. pri_spec_copy = *pri_spec;
  6885. nghttp2_priority_spec_normalize_weight(&pri_spec_copy);
  6886. stream =
  6887. nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE,
  6888. &pri_spec_copy, NGHTTP2_STREAM_IDLE, NULL);
  6889. if (!stream) {
  6890. return NGHTTP2_ERR_NOMEM;
  6891. }
  6892. /* We don't intentionally call nghttp2_session_adjust_idle_stream()
  6893. so that idle stream created by this function, and existing ones
  6894. are kept for application. We will adjust number of idle stream
  6895. in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is
  6896. called. */
  6897. return 0;
  6898. }
  6899. size_t
  6900. nghttp2_session_get_hd_inflate_dynamic_table_size(nghttp2_session *session) {
  6901. return nghttp2_hd_inflate_get_dynamic_table_size(&session->hd_inflater);
  6902. }
  6903. size_t
  6904. nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session) {
  6905. return nghttp2_hd_deflate_get_dynamic_table_size(&session->hd_deflater);
  6906. }
  6907. void nghttp2_session_set_user_data(nghttp2_session *session, void *user_data) {
  6908. session->user_data = user_data;
  6909. }
  6910. int nghttp2_session_change_extpri_stream_priority(
  6911. nghttp2_session *session, int32_t stream_id, const nghttp2_extpri *extpri_in,
  6912. int ignore_client_signal) {
  6913. nghttp2_stream *stream;
  6914. nghttp2_extpri extpri = *extpri_in;
  6915. if (!session->server) {
  6916. return NGHTTP2_ERR_INVALID_STATE;
  6917. }
  6918. if (session->pending_no_rfc7540_priorities != 1) {
  6919. return 0;
  6920. }
  6921. if (stream_id == 0) {
  6922. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6923. }
  6924. stream = nghttp2_session_get_stream_raw(session, stream_id);
  6925. if (!stream) {
  6926. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6927. }
  6928. if (extpri.urgency > NGHTTP2_EXTPRI_URGENCY_LOW) {
  6929. extpri.urgency = NGHTTP2_EXTPRI_URGENCY_LOW;
  6930. }
  6931. if (ignore_client_signal) {
  6932. stream->flags |= NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES;
  6933. }
  6934. return session_update_stream_priority(session, stream,
  6935. nghttp2_extpri_to_uint8(&extpri));
  6936. }
  6937. int nghttp2_session_get_extpri_stream_priority(nghttp2_session *session,
  6938. nghttp2_extpri *extpri,
  6939. int32_t stream_id) {
  6940. nghttp2_stream *stream;
  6941. if (!session->server) {
  6942. return NGHTTP2_ERR_INVALID_STATE;
  6943. }
  6944. if (session->pending_no_rfc7540_priorities != 1) {
  6945. return 0;
  6946. }
  6947. if (stream_id == 0) {
  6948. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6949. }
  6950. stream = nghttp2_session_get_stream_raw(session, stream_id);
  6951. if (!stream) {
  6952. return NGHTTP2_ERR_INVALID_ARGUMENT;
  6953. }
  6954. nghttp2_extpri_from_uint8(extpri, stream->extpri);
  6955. return 0;
  6956. }