http2.c 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "curl_setup.h"
  25. #ifdef USE_NGHTTP2
  26. #include <nghttp2/nghttp2.h>
  27. #include "urldata.h"
  28. #include "http2.h"
  29. #include "http.h"
  30. #include "sendf.h"
  31. #include "select.h"
  32. #include "curl_base64.h"
  33. #include "strcase.h"
  34. #include "multiif.h"
  35. #include "url.h"
  36. #include "cfilters.h"
  37. #include "connect.h"
  38. #include "strtoofft.h"
  39. #include "strdup.h"
  40. #include "transfer.h"
  41. #include "dynbuf.h"
  42. #include "h2h3.h"
  43. #include "headers.h"
  44. /* The last 3 #include files should be in this order */
  45. #include "curl_printf.h"
  46. #include "curl_memory.h"
  47. #include "memdebug.h"
  48. #define H2_BUFSIZE 32768
  49. #if (NGHTTP2_VERSION_NUM < 0x010c00)
  50. #error too old nghttp2 version, upgrade!
  51. #endif
  52. #ifdef CURL_DISABLE_VERBOSE_STRINGS
  53. #define nghttp2_session_callbacks_set_error_callback(x,y)
  54. #endif
  55. #if (NGHTTP2_VERSION_NUM >= 0x010c00)
  56. #define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
  57. #endif
  58. #define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */
  59. #define H2_SETTINGS_IV_LEN 3
  60. #define H2_BINSETTINGS_LEN 80
  61. static int populate_settings(nghttp2_settings_entry *iv,
  62. struct Curl_easy *data)
  63. {
  64. iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
  65. iv[0].value = Curl_multi_max_concurrent_streams(data->multi);
  66. iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
  67. iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
  68. iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
  69. iv[2].value = data->multi->push_cb != NULL;
  70. return 3;
  71. }
  72. static size_t populate_binsettings(uint8_t *binsettings,
  73. struct Curl_easy *data)
  74. {
  75. nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
  76. int ivlen;
  77. ivlen = populate_settings(iv, data);
  78. /* this returns number of bytes it wrote */
  79. return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
  80. iv, ivlen);
  81. }
  82. struct cf_h2_ctx {
  83. nghttp2_session *h2;
  84. uint32_t max_concurrent_streams;
  85. /* The easy handle used in the current filter call, cleared at return */
  86. struct cf_call_data call_data;
  87. char *inbuf; /* buffer to receive data from underlying socket */
  88. size_t inbuflen; /* number of bytes filled in inbuf */
  89. size_t nread_inbuf; /* number of bytes read from in inbuf */
  90. struct dynbuf outbuf;
  91. /* We need separate buffer for transmission and reception because we
  92. may call nghttp2_session_send() after the
  93. nghttp2_session_mem_recv() but mem buffer is still not full. In
  94. this case, we wrongly sends the content of mem buffer if we share
  95. them for both cases. */
  96. int32_t pause_stream_id; /* stream ID which paused
  97. nghttp2_session_mem_recv */
  98. size_t drain_total; /* sum of all stream's UrlState.drain */
  99. int32_t goaway_error;
  100. int32_t last_stream_id;
  101. BIT(goaway);
  102. BIT(enable_push);
  103. };
  104. /* How to access `call_data` from a cf_h2 filter */
  105. #define CF_CTX_CALL_DATA(cf) \
  106. ((struct cf_h2_ctx *)(cf)->ctx)->call_data
  107. static void cf_h2_ctx_clear(struct cf_h2_ctx *ctx)
  108. {
  109. struct cf_call_data save = ctx->call_data;
  110. if(ctx->h2) {
  111. nghttp2_session_del(ctx->h2);
  112. }
  113. free(ctx->inbuf);
  114. Curl_dyn_free(&ctx->outbuf);
  115. memset(ctx, 0, sizeof(*ctx));
  116. ctx->call_data = save;
  117. }
  118. static void cf_h2_ctx_free(struct cf_h2_ctx *ctx)
  119. {
  120. if(ctx) {
  121. cf_h2_ctx_clear(ctx);
  122. free(ctx);
  123. }
  124. }
  125. static int h2_client_new(struct Curl_cfilter *cf,
  126. nghttp2_session_callbacks *cbs)
  127. {
  128. struct cf_h2_ctx *ctx = cf->ctx;
  129. #if NGHTTP2_VERSION_NUM < 0x013200
  130. /* before 1.50.0 */
  131. return nghttp2_session_client_new(&ctx->h2, cbs, cf);
  132. #else
  133. nghttp2_option *o;
  134. int rc = nghttp2_option_new(&o);
  135. if(rc)
  136. return rc;
  137. /* turn off RFC 9113 leading and trailing white spaces validation against
  138. HTTP field value. */
  139. nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1);
  140. rc = nghttp2_session_client_new2(&ctx->h2, cbs, cf, o);
  141. nghttp2_option_del(o);
  142. return rc;
  143. #endif
  144. }
  145. static ssize_t send_callback(nghttp2_session *h2,
  146. const uint8_t *mem, size_t length, int flags,
  147. void *userp);
  148. static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
  149. void *userp);
  150. static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
  151. int32_t stream_id,
  152. const uint8_t *mem, size_t len, void *userp);
  153. static int on_stream_close(nghttp2_session *session, int32_t stream_id,
  154. uint32_t error_code, void *userp);
  155. static int on_begin_headers(nghttp2_session *session,
  156. const nghttp2_frame *frame, void *userp);
  157. static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
  158. const uint8_t *name, size_t namelen,
  159. const uint8_t *value, size_t valuelen,
  160. uint8_t flags,
  161. void *userp);
  162. static int error_callback(nghttp2_session *session, const char *msg,
  163. size_t len, void *userp);
  164. /*
  165. * multi_connchanged() is called to tell that there is a connection in
  166. * this multi handle that has changed state (multiplexing become possible, the
  167. * number of allowed streams changed or similar), and a subsequent use of this
  168. * multi handle should move CONNECT_PEND handles back to CONNECT to have them
  169. * retry.
  170. */
  171. static void multi_connchanged(struct Curl_multi *multi)
  172. {
  173. multi->recheckstate = TRUE;
  174. }
  175. static CURLcode http2_data_setup(struct Curl_cfilter *cf,
  176. struct Curl_easy *data)
  177. {
  178. struct HTTP *stream = data->req.p.http;
  179. (void)cf;
  180. DEBUGASSERT(stream);
  181. DEBUGASSERT(data->state.buffer);
  182. stream->stream_id = -1;
  183. Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
  184. Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS);
  185. stream->bodystarted = FALSE;
  186. stream->status_code = -1;
  187. stream->pausedata = NULL;
  188. stream->pauselen = 0;
  189. stream->closed = FALSE;
  190. stream->close_handled = FALSE;
  191. stream->memlen = 0;
  192. stream->error = NGHTTP2_NO_ERROR;
  193. stream->upload_left = 0;
  194. stream->upload_mem = NULL;
  195. stream->upload_len = 0;
  196. stream->mem = data->state.buffer;
  197. stream->len = data->set.buffer_size;
  198. return CURLE_OK;
  199. }
  200. /*
  201. * Initialize the cfilter context
  202. */
  203. static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
  204. struct Curl_easy *data,
  205. bool via_h1_upgrade)
  206. {
  207. struct cf_h2_ctx *ctx = cf->ctx;
  208. struct HTTP *stream = data->req.p.http;
  209. CURLcode result = CURLE_OUT_OF_MEMORY;
  210. int rc;
  211. nghttp2_session_callbacks *cbs = NULL;
  212. DEBUGASSERT(!ctx->h2);
  213. ctx->inbuf = malloc(H2_BUFSIZE);
  214. if(!ctx->inbuf)
  215. goto out;
  216. /* we want to aggregate small frames, SETTINGS, PRIO, UPDATES */
  217. Curl_dyn_init(&ctx->outbuf, 4*1024);
  218. rc = nghttp2_session_callbacks_new(&cbs);
  219. if(rc) {
  220. failf(data, "Couldn't initialize nghttp2 callbacks");
  221. goto out;
  222. }
  223. nghttp2_session_callbacks_set_send_callback(cbs, send_callback);
  224. nghttp2_session_callbacks_set_on_frame_recv_callback(cbs, on_frame_recv);
  225. nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
  226. cbs, on_data_chunk_recv);
  227. nghttp2_session_callbacks_set_on_stream_close_callback(cbs, on_stream_close);
  228. nghttp2_session_callbacks_set_on_begin_headers_callback(
  229. cbs, on_begin_headers);
  230. nghttp2_session_callbacks_set_on_header_callback(cbs, on_header);
  231. nghttp2_session_callbacks_set_error_callback(cbs, error_callback);
  232. /* The nghttp2 session is not yet setup, do it */
  233. rc = h2_client_new(cf, cbs);
  234. if(rc) {
  235. failf(data, "Couldn't initialize nghttp2");
  236. goto out;
  237. }
  238. ctx->max_concurrent_streams = DEFAULT_MAX_CONCURRENT_STREAMS;
  239. result = http2_data_setup(cf, data);
  240. if(result)
  241. goto out;
  242. if(via_h1_upgrade) {
  243. /* HTTP/1.1 Upgrade issued. H2 Settings have already been submitted
  244. * in the H1 request and we upgrade from there. This stream
  245. * is opened implicitly as #1. */
  246. uint8_t binsettings[H2_BINSETTINGS_LEN];
  247. size_t binlen; /* length of the binsettings data */
  248. binlen = populate_binsettings(binsettings, data);
  249. stream->stream_id = 1;
  250. /* queue SETTINGS frame (again) */
  251. rc = nghttp2_session_upgrade2(ctx->h2, binsettings, binlen,
  252. data->state.httpreq == HTTPREQ_HEAD,
  253. NULL);
  254. if(rc) {
  255. failf(data, "nghttp2_session_upgrade2() failed: %s(%d)",
  256. nghttp2_strerror(rc), rc);
  257. result = CURLE_HTTP2;
  258. goto out;
  259. }
  260. rc = nghttp2_session_set_stream_user_data(ctx->h2, stream->stream_id,
  261. data);
  262. if(rc) {
  263. infof(data, "http/2: failed to set user_data for stream %u",
  264. stream->stream_id);
  265. DEBUGASSERT(0);
  266. }
  267. }
  268. else {
  269. nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
  270. int ivlen;
  271. /* H2 Settings need to be submitted. Stream is not open yet. */
  272. DEBUGASSERT(stream->stream_id == -1);
  273. ivlen = populate_settings(iv, data);
  274. rc = nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE,
  275. iv, ivlen);
  276. if(rc) {
  277. failf(data, "nghttp2_submit_settings() failed: %s(%d)",
  278. nghttp2_strerror(rc), rc);
  279. result = CURLE_HTTP2;
  280. goto out;
  281. }
  282. }
  283. rc = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE, 0,
  284. HTTP2_HUGE_WINDOW_SIZE);
  285. if(rc) {
  286. failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
  287. nghttp2_strerror(rc), rc);
  288. result = CURLE_HTTP2;
  289. goto out;
  290. }
  291. /* all set, traffic will be send on connect */
  292. result = CURLE_OK;
  293. out:
  294. if(cbs)
  295. nghttp2_session_callbacks_del(cbs);
  296. return result;
  297. }
  298. static CURLcode h2_session_send(struct Curl_cfilter *cf,
  299. struct Curl_easy *data);
  300. static int h2_process_pending_input(struct Curl_cfilter *cf,
  301. struct Curl_easy *data,
  302. CURLcode *err);
  303. /*
  304. * http2_stream_free() free HTTP2 stream related data
  305. */
  306. static void http2_stream_free(struct HTTP *stream)
  307. {
  308. if(stream) {
  309. Curl_dyn_free(&stream->header_recvbuf);
  310. for(; stream->push_headers_used > 0; --stream->push_headers_used) {
  311. free(stream->push_headers[stream->push_headers_used - 1]);
  312. }
  313. free(stream->push_headers);
  314. stream->push_headers = NULL;
  315. }
  316. }
  317. /*
  318. * Returns nonzero if current HTTP/2 session should be closed.
  319. */
  320. static int should_close_session(struct cf_h2_ctx *ctx)
  321. {
  322. return ctx->drain_total == 0 && !nghttp2_session_want_read(ctx->h2) &&
  323. !nghttp2_session_want_write(ctx->h2);
  324. }
  325. /*
  326. * The server may send us data at any point (e.g. PING frames). Therefore,
  327. * we cannot assume that an HTTP/2 socket is dead just because it is readable.
  328. *
  329. * Check the lower filters first and, if successful, peek at the socket
  330. * and distinguish between closed and data.
  331. */
  332. static bool http2_connisalive(struct Curl_cfilter *cf, struct Curl_easy *data,
  333. bool *input_pending)
  334. {
  335. struct cf_h2_ctx *ctx = cf->ctx;
  336. bool alive = TRUE;
  337. *input_pending = FALSE;
  338. if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
  339. return FALSE;
  340. if(*input_pending) {
  341. /* This happens before we've sent off a request and the connection is
  342. not in use by any other transfer, there shouldn't be any data here,
  343. only "protocol frames" */
  344. CURLcode result;
  345. ssize_t nread = -1;
  346. *input_pending = FALSE;
  347. Curl_attach_connection(data, cf->conn);
  348. nread = Curl_conn_cf_recv(cf->next, data,
  349. ctx->inbuf, H2_BUFSIZE, &result);
  350. if(nread != -1) {
  351. DEBUGF(LOG_CF(data, cf, "%d bytes stray data read before trying "
  352. "h2 connection", (int)nread));
  353. ctx->nread_inbuf = 0;
  354. ctx->inbuflen = nread;
  355. if(h2_process_pending_input(cf, data, &result) < 0)
  356. /* immediate error, considered dead */
  357. alive = FALSE;
  358. else {
  359. alive = !should_close_session(ctx);
  360. }
  361. }
  362. else {
  363. /* the read failed so let's say this is dead anyway */
  364. alive = FALSE;
  365. }
  366. Curl_detach_connection(data);
  367. }
  368. return alive;
  369. }
  370. static CURLcode http2_send_ping(struct Curl_cfilter *cf,
  371. struct Curl_easy *data)
  372. {
  373. struct cf_h2_ctx *ctx = cf->ctx;
  374. int rc;
  375. rc = nghttp2_submit_ping(ctx->h2, 0, ZERO_NULL);
  376. if(rc) {
  377. failf(data, "nghttp2_submit_ping() failed: %s(%d)",
  378. nghttp2_strerror(rc), rc);
  379. return CURLE_HTTP2;
  380. }
  381. rc = nghttp2_session_send(ctx->h2);
  382. if(rc) {
  383. failf(data, "nghttp2_session_send() failed: %s(%d)",
  384. nghttp2_strerror(rc), rc);
  385. return CURLE_SEND_ERROR;
  386. }
  387. return CURLE_OK;
  388. }
  389. /*
  390. * Store nghttp2 version info in this buffer.
  391. */
  392. void Curl_http2_ver(char *p, size_t len)
  393. {
  394. nghttp2_info *h2 = nghttp2_version(0);
  395. (void)msnprintf(p, len, "nghttp2/%s", h2->version_str);
  396. }
  397. static CURLcode flush_output(struct Curl_cfilter *cf,
  398. struct Curl_easy *data)
  399. {
  400. struct cf_h2_ctx *ctx = cf->ctx;
  401. size_t buflen = Curl_dyn_len(&ctx->outbuf);
  402. ssize_t written;
  403. CURLcode result;
  404. if(!buflen)
  405. return CURLE_OK;
  406. DEBUGF(LOG_CF(data, cf, "h2 conn flush %zu bytes", buflen));
  407. written = Curl_conn_cf_send(cf->next, data, Curl_dyn_ptr(&ctx->outbuf),
  408. buflen, &result);
  409. if(written < 0) {
  410. return result;
  411. }
  412. if((size_t)written < buflen) {
  413. Curl_dyn_tail(&ctx->outbuf, buflen - (size_t)written);
  414. return CURLE_AGAIN;
  415. }
  416. else {
  417. Curl_dyn_reset(&ctx->outbuf);
  418. }
  419. return CURLE_OK;
  420. }
  421. /*
  422. * The implementation of nghttp2_send_callback type. Here we write |data| with
  423. * size |length| to the network and return the number of bytes actually
  424. * written. See the documentation of nghttp2_send_callback for the details.
  425. */
  426. static ssize_t send_callback(nghttp2_session *h2,
  427. const uint8_t *buf, size_t blen, int flags,
  428. void *userp)
  429. {
  430. struct Curl_cfilter *cf = userp;
  431. struct cf_h2_ctx *ctx = cf->ctx;
  432. struct Curl_easy *data = CF_DATA_CURRENT(cf);
  433. ssize_t written;
  434. CURLcode result = CURLE_OK;
  435. size_t buflen = Curl_dyn_len(&ctx->outbuf);
  436. (void)h2;
  437. (void)flags;
  438. DEBUGASSERT(data);
  439. if(blen < 1024 && (buflen + blen + 1 < ctx->outbuf.toobig)) {
  440. result = Curl_dyn_addn(&ctx->outbuf, buf, blen);
  441. if(result) {
  442. failf(data, "Failed to add data to output buffer");
  443. return NGHTTP2_ERR_CALLBACK_FAILURE;
  444. }
  445. return blen;
  446. }
  447. if(buflen) {
  448. /* not adding, flush buffer */
  449. result = flush_output(cf, data);
  450. if(result) {
  451. if(result == CURLE_AGAIN) {
  452. return NGHTTP2_ERR_WOULDBLOCK;
  453. }
  454. failf(data, "Failed sending HTTP2 data");
  455. return NGHTTP2_ERR_CALLBACK_FAILURE;
  456. }
  457. }
  458. DEBUGF(LOG_CF(data, cf, "h2 conn send %zu bytes", blen));
  459. written = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
  460. if(result == CURLE_AGAIN) {
  461. return NGHTTP2_ERR_WOULDBLOCK;
  462. }
  463. if(written == -1) {
  464. failf(data, "Failed sending HTTP2 data");
  465. return NGHTTP2_ERR_CALLBACK_FAILURE;
  466. }
  467. if(!written)
  468. return NGHTTP2_ERR_WOULDBLOCK;
  469. return written;
  470. }
  471. /* We pass a pointer to this struct in the push callback, but the contents of
  472. the struct are hidden from the user. */
  473. struct curl_pushheaders {
  474. struct Curl_easy *data;
  475. const nghttp2_push_promise *frame;
  476. };
  477. /*
  478. * push header access function. Only to be used from within the push callback
  479. */
  480. char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
  481. {
  482. /* Verify that we got a good easy handle in the push header struct, mostly to
  483. detect rubbish input fast(er). */
  484. if(!h || !GOOD_EASY_HANDLE(h->data))
  485. return NULL;
  486. else {
  487. struct HTTP *stream = h->data->req.p.http;
  488. if(num < stream->push_headers_used)
  489. return stream->push_headers[num];
  490. }
  491. return NULL;
  492. }
  493. /*
  494. * push header access function. Only to be used from within the push callback
  495. */
  496. char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
  497. {
  498. /* Verify that we got a good easy handle in the push header struct,
  499. mostly to detect rubbish input fast(er). Also empty header name
  500. is just a rubbish too. We have to allow ":" at the beginning of
  501. the header, but header == ":" must be rejected. If we have ':' in
  502. the middle of header, it could be matched in middle of the value,
  503. this is because we do prefix match.*/
  504. if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] ||
  505. !strcmp(header, ":") || strchr(header + 1, ':'))
  506. return NULL;
  507. else {
  508. struct HTTP *stream = h->data->req.p.http;
  509. size_t len = strlen(header);
  510. size_t i;
  511. for(i = 0; i<stream->push_headers_used; i++) {
  512. if(!strncmp(header, stream->push_headers[i], len)) {
  513. /* sub-match, make sure that it is followed by a colon */
  514. if(stream->push_headers[i][len] != ':')
  515. continue;
  516. return &stream->push_headers[i][len + 1];
  517. }
  518. }
  519. }
  520. return NULL;
  521. }
  522. /*
  523. * This specific transfer on this connection has been "drained".
  524. */
  525. static void drained_transfer(struct Curl_cfilter *cf,
  526. struct Curl_easy *data)
  527. {
  528. if(data->state.drain) {
  529. struct cf_h2_ctx *ctx = cf->ctx;
  530. DEBUGASSERT(ctx->drain_total > 0);
  531. ctx->drain_total--;
  532. data->state.drain = 0;
  533. }
  534. }
  535. /*
  536. * Mark this transfer to get "drained".
  537. */
  538. static void drain_this(struct Curl_cfilter *cf,
  539. struct Curl_easy *data)
  540. {
  541. if(!data->state.drain) {
  542. struct cf_h2_ctx *ctx = cf->ctx;
  543. data->state.drain = 1;
  544. ctx->drain_total++;
  545. DEBUGASSERT(ctx->drain_total > 0);
  546. }
  547. }
  548. static struct Curl_easy *h2_duphandle(struct Curl_cfilter *cf,
  549. struct Curl_easy *data)
  550. {
  551. struct Curl_easy *second = curl_easy_duphandle(data);
  552. if(second) {
  553. /* setup the request struct */
  554. struct HTTP *http = calloc(1, sizeof(struct HTTP));
  555. if(!http) {
  556. (void)Curl_close(&second);
  557. }
  558. else {
  559. second->req.p.http = http;
  560. http2_data_setup(cf, second);
  561. second->state.priority.weight = data->state.priority.weight;
  562. }
  563. }
  564. return second;
  565. }
  566. static int set_transfer_url(struct Curl_easy *data,
  567. struct curl_pushheaders *hp)
  568. {
  569. const char *v;
  570. CURLUcode uc;
  571. char *url = NULL;
  572. int rc = 0;
  573. CURLU *u = curl_url();
  574. if(!u)
  575. return 5;
  576. v = curl_pushheader_byname(hp, H2H3_PSEUDO_SCHEME);
  577. if(v) {
  578. uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
  579. if(uc) {
  580. rc = 1;
  581. goto fail;
  582. }
  583. }
  584. v = curl_pushheader_byname(hp, H2H3_PSEUDO_AUTHORITY);
  585. if(v) {
  586. uc = curl_url_set(u, CURLUPART_HOST, v, 0);
  587. if(uc) {
  588. rc = 2;
  589. goto fail;
  590. }
  591. }
  592. v = curl_pushheader_byname(hp, H2H3_PSEUDO_PATH);
  593. if(v) {
  594. uc = curl_url_set(u, CURLUPART_PATH, v, 0);
  595. if(uc) {
  596. rc = 3;
  597. goto fail;
  598. }
  599. }
  600. uc = curl_url_get(u, CURLUPART_URL, &url, 0);
  601. if(uc)
  602. rc = 4;
  603. fail:
  604. curl_url_cleanup(u);
  605. if(rc)
  606. return rc;
  607. if(data->state.url_alloc)
  608. free(data->state.url);
  609. data->state.url_alloc = TRUE;
  610. data->state.url = url;
  611. return 0;
  612. }
  613. static int push_promise(struct Curl_cfilter *cf,
  614. struct Curl_easy *data,
  615. const nghttp2_push_promise *frame)
  616. {
  617. struct cf_h2_ctx *ctx = cf->ctx;
  618. int rv; /* one of the CURL_PUSH_* defines */
  619. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] PUSH_PROMISE received",
  620. frame->promised_stream_id));
  621. if(data->multi->push_cb) {
  622. struct HTTP *stream;
  623. struct HTTP *newstream;
  624. struct curl_pushheaders heads;
  625. CURLMcode rc;
  626. size_t i;
  627. /* clone the parent */
  628. struct Curl_easy *newhandle = h2_duphandle(cf, data);
  629. if(!newhandle) {
  630. infof(data, "failed to duplicate handle");
  631. rv = CURL_PUSH_DENY; /* FAIL HARD */
  632. goto fail;
  633. }
  634. heads.data = data;
  635. heads.frame = frame;
  636. /* ask the application */
  637. DEBUGF(LOG_CF(data, cf, "Got PUSH_PROMISE, ask application"));
  638. stream = data->req.p.http;
  639. if(!stream) {
  640. failf(data, "Internal NULL stream");
  641. (void)Curl_close(&newhandle);
  642. rv = CURL_PUSH_DENY;
  643. goto fail;
  644. }
  645. rv = set_transfer_url(newhandle, &heads);
  646. if(rv) {
  647. (void)Curl_close(&newhandle);
  648. rv = CURL_PUSH_DENY;
  649. goto fail;
  650. }
  651. Curl_set_in_callback(data, true);
  652. rv = data->multi->push_cb(data, newhandle,
  653. stream->push_headers_used, &heads,
  654. data->multi->push_userp);
  655. Curl_set_in_callback(data, false);
  656. /* free the headers again */
  657. for(i = 0; i<stream->push_headers_used; i++)
  658. free(stream->push_headers[i]);
  659. free(stream->push_headers);
  660. stream->push_headers = NULL;
  661. stream->push_headers_used = 0;
  662. if(rv) {
  663. DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
  664. /* denied, kill off the new handle again */
  665. http2_stream_free(newhandle->req.p.http);
  666. newhandle->req.p.http = NULL;
  667. (void)Curl_close(&newhandle);
  668. goto fail;
  669. }
  670. newstream = newhandle->req.p.http;
  671. newstream->stream_id = frame->promised_stream_id;
  672. newhandle->req.maxdownload = -1;
  673. newhandle->req.size = -1;
  674. /* approved, add to the multi handle and immediately switch to PERFORM
  675. state with the given connection !*/
  676. rc = Curl_multi_add_perform(data->multi, newhandle, cf->conn);
  677. if(rc) {
  678. infof(data, "failed to add handle to multi");
  679. http2_stream_free(newhandle->req.p.http);
  680. newhandle->req.p.http = NULL;
  681. Curl_close(&newhandle);
  682. rv = CURL_PUSH_DENY;
  683. goto fail;
  684. }
  685. rv = nghttp2_session_set_stream_user_data(ctx->h2,
  686. frame->promised_stream_id,
  687. newhandle);
  688. if(rv) {
  689. infof(data, "failed to set user_data for stream %u",
  690. frame->promised_stream_id);
  691. DEBUGASSERT(0);
  692. rv = CURL_PUSH_DENY;
  693. goto fail;
  694. }
  695. Curl_dyn_init(&newstream->header_recvbuf, DYN_H2_HEADERS);
  696. Curl_dyn_init(&newstream->trailer_recvbuf, DYN_H2_TRAILERS);
  697. }
  698. else {
  699. DEBUGF(LOG_CF(data, cf, "Got PUSH_PROMISE, ignore it"));
  700. rv = CURL_PUSH_DENY;
  701. }
  702. fail:
  703. return rv;
  704. }
  705. static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
  706. void *userp)
  707. {
  708. struct Curl_cfilter *cf = userp;
  709. struct cf_h2_ctx *ctx = cf->ctx;
  710. struct Curl_easy *data_s = NULL;
  711. struct HTTP *stream = NULL;
  712. struct Curl_easy *data = CF_DATA_CURRENT(cf);
  713. int rv;
  714. size_t left, ncopy;
  715. int32_t stream_id = frame->hd.stream_id;
  716. CURLcode result;
  717. DEBUGASSERT(data);
  718. if(!stream_id) {
  719. /* stream ID zero is for connection-oriented stuff */
  720. DEBUGASSERT(data);
  721. switch(frame->hd.type) {
  722. case NGHTTP2_SETTINGS: {
  723. uint32_t max_conn = ctx->max_concurrent_streams;
  724. DEBUGF(LOG_CF(data, cf, "recv frame SETTINGS"));
  725. ctx->max_concurrent_streams = nghttp2_session_get_remote_settings(
  726. session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
  727. ctx->enable_push = nghttp2_session_get_remote_settings(
  728. session, NGHTTP2_SETTINGS_ENABLE_PUSH) != 0;
  729. DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS == %d",
  730. ctx->max_concurrent_streams));
  731. DEBUGF(LOG_CF(data, cf, "ENABLE_PUSH == %s",
  732. ctx->enable_push ? "TRUE" : "false"));
  733. if(data && max_conn != ctx->max_concurrent_streams) {
  734. /* only signal change if the value actually changed */
  735. DEBUGF(LOG_CF(data, cf, "MAX_CONCURRENT_STREAMS now %u",
  736. ctx->max_concurrent_streams));
  737. multi_connchanged(data->multi);
  738. }
  739. break;
  740. }
  741. case NGHTTP2_GOAWAY:
  742. ctx->goaway = TRUE;
  743. ctx->goaway_error = frame->goaway.error_code;
  744. ctx->last_stream_id = frame->goaway.last_stream_id;
  745. if(data) {
  746. infof(data, "recveived GOAWAY, error=%d, last_stream=%u",
  747. ctx->goaway_error, ctx->last_stream_id);
  748. multi_connchanged(data->multi);
  749. }
  750. break;
  751. case NGHTTP2_WINDOW_UPDATE:
  752. DEBUGF(LOG_CF(data, cf, "recv frame WINDOW_UPDATE"));
  753. break;
  754. default:
  755. DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
  756. }
  757. return 0;
  758. }
  759. data_s = nghttp2_session_get_stream_user_data(session, stream_id);
  760. if(!data_s) {
  761. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] No Curl_easy associated",
  762. stream_id));
  763. return 0;
  764. }
  765. stream = data_s->req.p.http;
  766. if(!stream) {
  767. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] No proto pointer", stream_id));
  768. return NGHTTP2_ERR_CALLBACK_FAILURE;
  769. }
  770. switch(frame->hd.type) {
  771. case NGHTTP2_DATA:
  772. /* If !body started on this stream, then receiving DATA is illegal. */
  773. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] recv frame DATA", stream_id));
  774. if(!stream->bodystarted) {
  775. rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
  776. stream_id, NGHTTP2_PROTOCOL_ERROR);
  777. if(nghttp2_is_fatal(rv)) {
  778. return NGHTTP2_ERR_CALLBACK_FAILURE;
  779. }
  780. }
  781. if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
  782. /* Stream has ended. If there is pending data, ensure that read
  783. will occur to consume it. */
  784. if(!data->state.drain && stream->memlen) {
  785. drain_this(cf, data_s);
  786. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  787. }
  788. }
  789. break;
  790. case NGHTTP2_HEADERS:
  791. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] recv frame HEADERS", stream_id));
  792. if(stream->bodystarted) {
  793. /* Only valid HEADERS after body started is trailer HEADERS. We
  794. buffer them in on_header callback. */
  795. break;
  796. }
  797. /* nghttp2 guarantees that :status is received, and we store it to
  798. stream->status_code. Fuzzing has proven this can still be reached
  799. without status code having been set. */
  800. if(stream->status_code == -1)
  801. return NGHTTP2_ERR_CALLBACK_FAILURE;
  802. /* Only final status code signals the end of header */
  803. if(stream->status_code / 100 != 1) {
  804. stream->bodystarted = TRUE;
  805. stream->status_code = -1;
  806. }
  807. result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST("\r\n"));
  808. if(result)
  809. return NGHTTP2_ERR_CALLBACK_FAILURE;
  810. left = Curl_dyn_len(&stream->header_recvbuf) -
  811. stream->nread_header_recvbuf;
  812. ncopy = CURLMIN(stream->len, left);
  813. memcpy(&stream->mem[stream->memlen],
  814. Curl_dyn_ptr(&stream->header_recvbuf) +
  815. stream->nread_header_recvbuf,
  816. ncopy);
  817. stream->nread_header_recvbuf += ncopy;
  818. DEBUGASSERT(stream->mem);
  819. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] %zu header bytes, at %p",
  820. stream_id, ncopy, (void *)stream->mem));
  821. stream->len -= ncopy;
  822. stream->memlen += ncopy;
  823. drain_this(cf, data_s);
  824. Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
  825. break;
  826. case NGHTTP2_PUSH_PROMISE:
  827. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] recv PUSH_PROMISE", stream_id));
  828. rv = push_promise(cf, data_s, &frame->push_promise);
  829. if(rv) { /* deny! */
  830. int h2;
  831. DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
  832. h2 = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
  833. frame->push_promise.promised_stream_id,
  834. NGHTTP2_CANCEL);
  835. if(nghttp2_is_fatal(h2))
  836. return NGHTTP2_ERR_CALLBACK_FAILURE;
  837. else if(rv == CURL_PUSH_ERROROUT) {
  838. DEBUGF(LOG_CF(data_s, cf, "Fail the parent stream (too)"));
  839. return NGHTTP2_ERR_CALLBACK_FAILURE;
  840. }
  841. }
  842. break;
  843. case NGHTTP2_RST_STREAM:
  844. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] recv RST", stream_id));
  845. stream->closed = TRUE;
  846. stream->reset = TRUE;
  847. drain_this(cf, data);
  848. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  849. break;
  850. case NGHTTP2_WINDOW_UPDATE:
  851. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv WINDOW_UPDATE", stream_id));
  852. if((data_s->req.keepon & KEEP_SEND_HOLD) &&
  853. (data_s->req.keepon & KEEP_SEND)) {
  854. data_s->req.keepon &= ~KEEP_SEND_HOLD;
  855. drain_this(cf, data_s);
  856. Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
  857. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] un-holding after win update",
  858. stream_id));
  859. }
  860. break;
  861. default:
  862. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] recv frame %x",
  863. stream_id, frame->hd.type));
  864. break;
  865. }
  866. return 0;
  867. }
  868. static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
  869. int32_t stream_id,
  870. const uint8_t *mem, size_t len, void *userp)
  871. {
  872. struct Curl_cfilter *cf = userp;
  873. struct cf_h2_ctx *ctx = cf->ctx;
  874. struct HTTP *stream;
  875. struct Curl_easy *data_s;
  876. size_t nread;
  877. (void)flags;
  878. DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
  879. DEBUGASSERT(CF_DATA_CURRENT(cf));
  880. /* get the stream from the hash based on Stream ID */
  881. data_s = nghttp2_session_get_stream_user_data(session, stream_id);
  882. if(!data_s) {
  883. /* Receiving a Stream ID not in the hash should not happen - unless
  884. we have aborted a transfer artificially and there were more data
  885. in the pipeline. Silently ignore. */
  886. DEBUGF(LOG_CF(CF_DATA_CURRENT(cf), cf, "[h2sid=%u] Data for unknown",
  887. stream_id));
  888. return 0;
  889. }
  890. stream = data_s->req.p.http;
  891. if(!stream)
  892. return NGHTTP2_ERR_CALLBACK_FAILURE;
  893. nread = CURLMIN(stream->len, len);
  894. memcpy(&stream->mem[stream->memlen], mem, nread);
  895. stream->len -= nread;
  896. stream->memlen += nread;
  897. /* if we receive data for another handle, wake that up */
  898. if(CF_DATA_CURRENT(cf) != data_s) {
  899. drain_this(cf, data_s);
  900. Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
  901. }
  902. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] %zu DATA recvd, "
  903. "(buffer now holds %zu, %zu still free in %p)",
  904. stream_id, nread,
  905. stream->memlen, stream->len, (void *)stream->mem));
  906. if(nread < len) {
  907. stream->pausedata = mem + nread;
  908. stream->pauselen = len - nread;
  909. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] %zu not recvd -> NGHTTP2_ERR_PAUSE",
  910. stream_id, len - nread));
  911. ctx->pause_stream_id = stream_id;
  912. drain_this(cf, data_s);
  913. return NGHTTP2_ERR_PAUSE;
  914. }
  915. return 0;
  916. }
  917. static int on_stream_close(nghttp2_session *session, int32_t stream_id,
  918. uint32_t error_code, void *userp)
  919. {
  920. struct Curl_cfilter *cf = userp;
  921. struct cf_h2_ctx *ctx = cf->ctx;
  922. struct Curl_easy *data_s;
  923. struct HTTP *stream;
  924. int rv;
  925. (void)session;
  926. /* get the stream from the hash based on Stream ID, stream ID zero is for
  927. connection-oriented stuff */
  928. data_s = stream_id?
  929. nghttp2_session_get_stream_user_data(session, stream_id) : NULL;
  930. if(!data_s) {
  931. return 0;
  932. }
  933. stream = data_s->req.p.http;
  934. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] on_stream_close(), %s (err %d)",
  935. stream_id, nghttp2_http2_strerror(error_code), error_code));
  936. if(!stream)
  937. return NGHTTP2_ERR_CALLBACK_FAILURE;
  938. stream->closed = TRUE;
  939. stream->error = error_code;
  940. if(stream->error)
  941. stream->reset = TRUE;
  942. if(CF_DATA_CURRENT(cf) != data_s) {
  943. drain_this(cf, data_s);
  944. Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
  945. }
  946. /* remove `data_s` from the nghttp2 stream */
  947. rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
  948. if(rv) {
  949. infof(data_s, "http/2: failed to clear user_data for stream %u",
  950. stream_id);
  951. DEBUGASSERT(0);
  952. }
  953. if(stream_id == ctx->pause_stream_id) {
  954. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] closed the pause stream",
  955. stream_id));
  956. ctx->pause_stream_id = 0;
  957. }
  958. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] closed now", stream_id));
  959. return 0;
  960. }
  961. static int on_begin_headers(nghttp2_session *session,
  962. const nghttp2_frame *frame, void *userp)
  963. {
  964. struct Curl_cfilter *cf = userp;
  965. struct HTTP *stream;
  966. struct Curl_easy *data_s = NULL;
  967. (void)cf;
  968. data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
  969. if(!data_s) {
  970. return 0;
  971. }
  972. DEBUGF(LOG_CF(data_s, cf, "on_begin_headers() was called"));
  973. if(frame->hd.type != NGHTTP2_HEADERS) {
  974. return 0;
  975. }
  976. stream = data_s->req.p.http;
  977. if(!stream || !stream->bodystarted) {
  978. return 0;
  979. }
  980. return 0;
  981. }
  982. /* Decode HTTP status code. Returns -1 if no valid status code was
  983. decoded. */
  984. static int decode_status_code(const uint8_t *value, size_t len)
  985. {
  986. int i;
  987. int res;
  988. if(len != 3) {
  989. return -1;
  990. }
  991. res = 0;
  992. for(i = 0; i < 3; ++i) {
  993. char c = value[i];
  994. if(c < '0' || c > '9') {
  995. return -1;
  996. }
  997. res *= 10;
  998. res += c - '0';
  999. }
  1000. return res;
  1001. }
  1002. /* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
  1003. static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
  1004. const uint8_t *name, size_t namelen,
  1005. const uint8_t *value, size_t valuelen,
  1006. uint8_t flags,
  1007. void *userp)
  1008. {
  1009. struct Curl_cfilter *cf = userp;
  1010. struct HTTP *stream;
  1011. struct Curl_easy *data_s;
  1012. int32_t stream_id = frame->hd.stream_id;
  1013. CURLcode result;
  1014. (void)flags;
  1015. DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
  1016. /* get the stream from the hash based on Stream ID */
  1017. data_s = nghttp2_session_get_stream_user_data(session, stream_id);
  1018. if(!data_s)
  1019. /* Receiving a Stream ID not in the hash should not happen, this is an
  1020. internal error more than anything else! */
  1021. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1022. stream = data_s->req.p.http;
  1023. if(!stream) {
  1024. failf(data_s, "Internal NULL stream");
  1025. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1026. }
  1027. /* Store received PUSH_PROMISE headers to be used when the subsequent
  1028. PUSH_PROMISE callback comes */
  1029. if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
  1030. char *h;
  1031. if(!strcmp(H2H3_PSEUDO_AUTHORITY, (const char *)name)) {
  1032. /* pseudo headers are lower case */
  1033. int rc = 0;
  1034. char *check = aprintf("%s:%d", cf->conn->host.name,
  1035. cf->conn->remote_port);
  1036. if(!check)
  1037. /* no memory */
  1038. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1039. if(!strcasecompare(check, (const char *)value) &&
  1040. ((cf->conn->remote_port != cf->conn->given->defport) ||
  1041. !strcasecompare(cf->conn->host.name, (const char *)value))) {
  1042. /* This is push is not for the same authority that was asked for in
  1043. * the URL. RFC 7540 section 8.2 says: "A client MUST treat a
  1044. * PUSH_PROMISE for which the server is not authoritative as a stream
  1045. * error of type PROTOCOL_ERROR."
  1046. */
  1047. (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
  1048. stream_id, NGHTTP2_PROTOCOL_ERROR);
  1049. rc = NGHTTP2_ERR_CALLBACK_FAILURE;
  1050. }
  1051. free(check);
  1052. if(rc)
  1053. return rc;
  1054. }
  1055. if(!stream->push_headers) {
  1056. stream->push_headers_alloc = 10;
  1057. stream->push_headers = malloc(stream->push_headers_alloc *
  1058. sizeof(char *));
  1059. if(!stream->push_headers)
  1060. return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
  1061. stream->push_headers_used = 0;
  1062. }
  1063. else if(stream->push_headers_used ==
  1064. stream->push_headers_alloc) {
  1065. char **headp;
  1066. if(stream->push_headers_alloc > 1000) {
  1067. /* this is beyond crazy many headers, bail out */
  1068. failf(data_s, "Too many PUSH_PROMISE headers");
  1069. Curl_safefree(stream->push_headers);
  1070. return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
  1071. }
  1072. stream->push_headers_alloc *= 2;
  1073. headp = Curl_saferealloc(stream->push_headers,
  1074. stream->push_headers_alloc * sizeof(char *));
  1075. if(!headp) {
  1076. stream->push_headers = NULL;
  1077. return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
  1078. }
  1079. stream->push_headers = headp;
  1080. }
  1081. h = aprintf("%s:%s", name, value);
  1082. if(h)
  1083. stream->push_headers[stream->push_headers_used++] = h;
  1084. return 0;
  1085. }
  1086. if(stream->bodystarted) {
  1087. /* This is a trailer */
  1088. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] trailer: %.*s: %.*s",
  1089. stream->stream_id,
  1090. (int)namelen, name,
  1091. (int)valuelen, value));
  1092. result = Curl_dyn_addf(&stream->trailer_recvbuf,
  1093. "%.*s: %.*s\r\n", (int)namelen, name,
  1094. (int)valuelen, value);
  1095. if(result)
  1096. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1097. return 0;
  1098. }
  1099. if(namelen == sizeof(H2H3_PSEUDO_STATUS) - 1 &&
  1100. memcmp(H2H3_PSEUDO_STATUS, name, namelen) == 0) {
  1101. /* nghttp2 guarantees :status is received first and only once, and
  1102. value is 3 digits status code, and decode_status_code always
  1103. succeeds. */
  1104. char buffer[32];
  1105. stream->status_code = decode_status_code(value, valuelen);
  1106. DEBUGASSERT(stream->status_code != -1);
  1107. msnprintf(buffer, sizeof(buffer), H2H3_PSEUDO_STATUS ":%u\r",
  1108. stream->status_code);
  1109. result = Curl_headers_push(data_s, buffer, CURLH_PSEUDO);
  1110. if(result)
  1111. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1112. result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST("HTTP/2 "));
  1113. if(result)
  1114. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1115. result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
  1116. if(result)
  1117. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1118. /* the space character after the status code is mandatory */
  1119. result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST(" \r\n"));
  1120. if(result)
  1121. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1122. /* if we receive data for another handle, wake that up */
  1123. if(CF_DATA_CURRENT(cf) != data_s)
  1124. Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
  1125. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] status: HTTP/2 %03d",
  1126. stream->stream_id, stream->status_code));
  1127. return 0;
  1128. }
  1129. /* nghttp2 guarantees that namelen > 0, and :status was already
  1130. received, and this is not pseudo-header field . */
  1131. /* convert to an HTTP1-style header */
  1132. result = Curl_dyn_addn(&stream->header_recvbuf, name, namelen);
  1133. if(result)
  1134. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1135. result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST(": "));
  1136. if(result)
  1137. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1138. result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
  1139. if(result)
  1140. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1141. result = Curl_dyn_addn(&stream->header_recvbuf, STRCONST("\r\n"));
  1142. if(result)
  1143. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1144. /* if we receive data for another handle, wake that up */
  1145. if(CF_DATA_CURRENT(cf) != data_s)
  1146. Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
  1147. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] header: %.*s: %.*s",
  1148. stream->stream_id,
  1149. (int)namelen, name,
  1150. (int)valuelen, value));
  1151. return 0; /* 0 is successful */
  1152. }
  1153. static ssize_t data_source_read_callback(nghttp2_session *session,
  1154. int32_t stream_id,
  1155. uint8_t *buf, size_t length,
  1156. uint32_t *data_flags,
  1157. nghttp2_data_source *source,
  1158. void *userp)
  1159. {
  1160. struct Curl_cfilter *cf = userp;
  1161. struct Curl_easy *data_s;
  1162. struct HTTP *stream = NULL;
  1163. size_t nread;
  1164. (void)source;
  1165. (void)cf;
  1166. if(stream_id) {
  1167. /* get the stream from the hash based on Stream ID, stream ID zero is for
  1168. connection-oriented stuff */
  1169. data_s = nghttp2_session_get_stream_user_data(session, stream_id);
  1170. if(!data_s)
  1171. /* Receiving a Stream ID not in the hash should not happen, this is an
  1172. internal error more than anything else! */
  1173. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1174. stream = data_s->req.p.http;
  1175. if(!stream)
  1176. return NGHTTP2_ERR_CALLBACK_FAILURE;
  1177. }
  1178. else
  1179. return NGHTTP2_ERR_INVALID_ARGUMENT;
  1180. nread = CURLMIN(stream->upload_len, length);
  1181. if(nread > 0) {
  1182. memcpy(buf, stream->upload_mem, nread);
  1183. stream->upload_mem += nread;
  1184. stream->upload_len -= nread;
  1185. if(data_s->state.infilesize != -1)
  1186. stream->upload_left -= nread;
  1187. }
  1188. if(stream->upload_left == 0)
  1189. *data_flags = NGHTTP2_DATA_FLAG_EOF;
  1190. else if(nread == 0)
  1191. return NGHTTP2_ERR_DEFERRED;
  1192. DEBUGF(LOG_CF(data_s, cf, "[h2sid=%u] data_source_read_callback: "
  1193. "returns %zu bytes", stream_id, nread));
  1194. return nread;
  1195. }
  1196. #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
  1197. static int error_callback(nghttp2_session *session,
  1198. const char *msg,
  1199. size_t len,
  1200. void *userp)
  1201. {
  1202. (void)session;
  1203. (void)msg;
  1204. (void)len;
  1205. (void)userp;
  1206. return 0;
  1207. }
  1208. #endif
  1209. static void http2_data_done(struct Curl_cfilter *cf,
  1210. struct Curl_easy *data, bool premature)
  1211. {
  1212. struct cf_h2_ctx *ctx = cf->ctx;
  1213. struct HTTP *stream = data->req.p.http;
  1214. /* there might be allocated resources done before this got the 'h2' pointer
  1215. setup */
  1216. Curl_dyn_free(&stream->header_recvbuf);
  1217. Curl_dyn_free(&stream->trailer_recvbuf);
  1218. if(stream->push_headers) {
  1219. /* if they weren't used and then freed before */
  1220. for(; stream->push_headers_used > 0; --stream->push_headers_used) {
  1221. free(stream->push_headers[stream->push_headers_used - 1]);
  1222. }
  1223. free(stream->push_headers);
  1224. stream->push_headers = NULL;
  1225. }
  1226. if(!ctx || !ctx->h2)
  1227. return;
  1228. /* do this before the reset handling, as that might clear ->stream_id */
  1229. if(stream->stream_id && stream->stream_id == ctx->pause_stream_id) {
  1230. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] DONE, the pause stream",
  1231. stream->stream_id));
  1232. ctx->pause_stream_id = 0;
  1233. }
  1234. (void)premature;
  1235. if(!stream->closed && stream->stream_id) {
  1236. /* RST_STREAM */
  1237. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] RST", stream->stream_id));
  1238. if(!nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
  1239. stream->stream_id, NGHTTP2_STREAM_CLOSED))
  1240. (void)nghttp2_session_send(ctx->h2);
  1241. }
  1242. if(data->state.drain)
  1243. drained_transfer(cf, data);
  1244. /* -1 means unassigned and 0 means cleared */
  1245. if(nghttp2_session_get_stream_user_data(ctx->h2, stream->stream_id)) {
  1246. int rv = nghttp2_session_set_stream_user_data(ctx->h2,
  1247. stream->stream_id, 0);
  1248. if(rv) {
  1249. infof(data, "http/2: failed to clear user_data for stream %u",
  1250. stream->stream_id);
  1251. DEBUGASSERT(0);
  1252. }
  1253. }
  1254. }
  1255. /*
  1256. * Append headers to ask for an HTTP1.1 to HTTP2 upgrade.
  1257. */
  1258. CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
  1259. struct Curl_easy *data)
  1260. {
  1261. CURLcode result;
  1262. char *base64;
  1263. size_t blen;
  1264. struct SingleRequest *k = &data->req;
  1265. uint8_t binsettings[H2_BINSETTINGS_LEN];
  1266. size_t binlen; /* length of the binsettings data */
  1267. binlen = populate_binsettings(binsettings, data);
  1268. if(binlen <= 0) {
  1269. failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
  1270. Curl_dyn_free(req);
  1271. return CURLE_FAILED_INIT;
  1272. }
  1273. result = Curl_base64url_encode((const char *)binsettings, binlen,
  1274. &base64, &blen);
  1275. if(result) {
  1276. Curl_dyn_free(req);
  1277. return result;
  1278. }
  1279. result = Curl_dyn_addf(req,
  1280. "Connection: Upgrade, HTTP2-Settings\r\n"
  1281. "Upgrade: %s\r\n"
  1282. "HTTP2-Settings: %s\r\n",
  1283. NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
  1284. free(base64);
  1285. k->upgr101 = UPGR101_H2;
  1286. return result;
  1287. }
  1288. /*
  1289. * h2_process_pending_input() processes pending input left in
  1290. * httpc->inbuf. Then, call h2_session_send() to send pending data.
  1291. * This function returns 0 if it succeeds, or -1 and error code will
  1292. * be assigned to *err.
  1293. */
  1294. static int h2_process_pending_input(struct Curl_cfilter *cf,
  1295. struct Curl_easy *data,
  1296. CURLcode *err)
  1297. {
  1298. struct cf_h2_ctx *ctx = cf->ctx;
  1299. ssize_t nread;
  1300. ssize_t rv;
  1301. nread = ctx->inbuflen - ctx->nread_inbuf;
  1302. if(nread) {
  1303. char *inbuf = ctx->inbuf + ctx->nread_inbuf;
  1304. rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)inbuf, nread);
  1305. if(rv < 0) {
  1306. failf(data,
  1307. "h2_process_pending_input: nghttp2_session_mem_recv() returned "
  1308. "%zd:%s", rv, nghttp2_strerror((int)rv));
  1309. *err = CURLE_RECV_ERROR;
  1310. return -1;
  1311. }
  1312. if(nread == rv) {
  1313. DEBUGF(LOG_CF(data, cf, "all data in connection buffer processed"));
  1314. ctx->inbuflen = 0;
  1315. ctx->nread_inbuf = 0;
  1316. }
  1317. else {
  1318. ctx->nread_inbuf += rv;
  1319. DEBUGF(LOG_CF(data, cf, "h2_process_pending_input: %zu bytes left "
  1320. "in connection buffer",
  1321. ctx->inbuflen - ctx->nread_inbuf));
  1322. }
  1323. }
  1324. rv = h2_session_send(cf, data);
  1325. if(rv) {
  1326. *err = CURLE_SEND_ERROR;
  1327. return -1;
  1328. }
  1329. if(nghttp2_session_check_request_allowed(ctx->h2) == 0) {
  1330. /* No more requests are allowed in the current session, so
  1331. the connection may not be reused. This is set when a
  1332. GOAWAY frame has been received or when the limit of stream
  1333. identifiers has been reached. */
  1334. connclose(cf->conn, "http/2: No new requests allowed");
  1335. }
  1336. if(should_close_session(ctx)) {
  1337. struct HTTP *stream = data->req.p.http;
  1338. DEBUGF(LOG_CF(data, cf,
  1339. "h2_process_pending_input: nothing to do in this session"));
  1340. if(stream->reset)
  1341. *err = CURLE_PARTIAL_FILE;
  1342. else if(stream->error)
  1343. *err = CURLE_HTTP2;
  1344. else {
  1345. /* not an error per se, but should still close the connection */
  1346. connclose(cf->conn, "GOAWAY received");
  1347. *err = CURLE_OK;
  1348. }
  1349. return -1;
  1350. }
  1351. return 0;
  1352. }
  1353. static CURLcode http2_data_done_send(struct Curl_cfilter *cf,
  1354. struct Curl_easy *data)
  1355. {
  1356. struct cf_h2_ctx *ctx = cf->ctx;
  1357. CURLcode result = CURLE_OK;
  1358. struct HTTP *stream = data->req.p.http;
  1359. if(!ctx || !ctx->h2)
  1360. goto out;
  1361. if(stream->upload_left) {
  1362. /* If the stream still thinks there's data left to upload. */
  1363. stream->upload_left = 0; /* DONE! */
  1364. /* resume sending here to trigger the callback to get called again so
  1365. that it can signal EOF to nghttp2 */
  1366. (void)nghttp2_session_resume_data(ctx->h2, stream->stream_id);
  1367. (void)h2_process_pending_input(cf, data, &result);
  1368. }
  1369. /* If nghttp2 still has pending frames unsent */
  1370. if(nghttp2_session_want_write(ctx->h2)) {
  1371. struct SingleRequest *k = &data->req;
  1372. int rv;
  1373. DEBUGF(LOG_CF(data, cf, "HTTP/2 still wants to send data"));
  1374. /* and attempt to send the pending frames */
  1375. rv = h2_session_send(cf, data);
  1376. if(rv)
  1377. result = CURLE_SEND_ERROR;
  1378. if(nghttp2_session_want_write(ctx->h2)) {
  1379. /* re-set KEEP_SEND to make sure we are called again */
  1380. k->keepon |= KEEP_SEND;
  1381. }
  1382. }
  1383. out:
  1384. return result;
  1385. }
  1386. static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
  1387. struct Curl_easy *data,
  1388. struct HTTP *stream, CURLcode *err)
  1389. {
  1390. struct cf_h2_ctx *ctx = cf->ctx;
  1391. if(ctx->pause_stream_id == stream->stream_id) {
  1392. ctx->pause_stream_id = 0;
  1393. }
  1394. drained_transfer(cf, data);
  1395. if(ctx->pause_stream_id == 0) {
  1396. if(h2_process_pending_input(cf, data, err) != 0) {
  1397. return -1;
  1398. }
  1399. }
  1400. if(stream->error == NGHTTP2_REFUSED_STREAM) {
  1401. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] REFUSED_STREAM, try again on a new "
  1402. "connection", stream->stream_id));
  1403. connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
  1404. data->state.refused_stream = TRUE;
  1405. *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
  1406. return -1;
  1407. }
  1408. else if(stream->error != NGHTTP2_NO_ERROR) {
  1409. failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
  1410. stream->stream_id, nghttp2_http2_strerror(stream->error),
  1411. stream->error);
  1412. *err = CURLE_HTTP2_STREAM;
  1413. return -1;
  1414. }
  1415. else if(stream->reset) {
  1416. failf(data, "HTTP/2 stream %u was reset", stream->stream_id);
  1417. *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
  1418. return -1;
  1419. }
  1420. if(!stream->bodystarted) {
  1421. failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
  1422. " all response header fields, treated as error",
  1423. stream->stream_id);
  1424. *err = CURLE_HTTP2_STREAM;
  1425. return -1;
  1426. }
  1427. if(Curl_dyn_len(&stream->trailer_recvbuf)) {
  1428. char *trailp = Curl_dyn_ptr(&stream->trailer_recvbuf);
  1429. char *lf;
  1430. do {
  1431. size_t len = 0;
  1432. CURLcode result;
  1433. /* each trailer line ends with a newline */
  1434. lf = strchr(trailp, '\n');
  1435. if(!lf)
  1436. break;
  1437. len = lf + 1 - trailp;
  1438. Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
  1439. /* pass the trailers one by one to the callback */
  1440. result = Curl_client_write(data, CLIENTWRITE_HEADER, trailp, len);
  1441. if(result) {
  1442. *err = result;
  1443. return -1;
  1444. }
  1445. trailp = ++lf;
  1446. } while(lf);
  1447. }
  1448. stream->close_handled = TRUE;
  1449. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] closed cleanly", stream->stream_id));
  1450. return 0;
  1451. }
  1452. static int sweight_wanted(const struct Curl_easy *data)
  1453. {
  1454. /* 0 weight is not set by user and we take the nghttp2 default one */
  1455. return data->set.priority.weight?
  1456. data->set.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
  1457. }
  1458. static int sweight_in_effect(const struct Curl_easy *data)
  1459. {
  1460. /* 0 weight is not set by user and we take the nghttp2 default one */
  1461. return data->state.priority.weight?
  1462. data->state.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
  1463. }
  1464. /*
  1465. * h2_pri_spec() fills in the pri_spec struct, used by nghttp2 to send weight
  1466. * and dependency to the peer. It also stores the updated values in the state
  1467. * struct.
  1468. */
  1469. static void h2_pri_spec(struct Curl_easy *data,
  1470. nghttp2_priority_spec *pri_spec)
  1471. {
  1472. struct Curl_data_priority *prio = &data->set.priority;
  1473. struct HTTP *depstream = (prio->parent?
  1474. prio->parent->req.p.http:NULL);
  1475. int32_t depstream_id = depstream? depstream->stream_id:0;
  1476. nghttp2_priority_spec_init(pri_spec, depstream_id,
  1477. sweight_wanted(data),
  1478. data->set.priority.exclusive);
  1479. data->state.priority = *prio;
  1480. }
  1481. /*
  1482. * h2_session_send() checks if there's been an update in the priority /
  1483. * dependency settings and if so it submits a PRIORITY frame with the updated
  1484. * info.
  1485. */
  1486. static CURLcode h2_session_send(struct Curl_cfilter *cf,
  1487. struct Curl_easy *data)
  1488. {
  1489. struct cf_h2_ctx *ctx = cf->ctx;
  1490. struct HTTP *stream = data->req.p.http;
  1491. int rv = 0;
  1492. if((sweight_wanted(data) != sweight_in_effect(data)) ||
  1493. (data->set.priority.exclusive != data->state.priority.exclusive) ||
  1494. (data->set.priority.parent != data->state.priority.parent) ) {
  1495. /* send new weight and/or dependency */
  1496. nghttp2_priority_spec pri_spec;
  1497. h2_pri_spec(data, &pri_spec);
  1498. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] Queuing PRIORITY",
  1499. stream->stream_id));
  1500. DEBUGASSERT(stream->stream_id != -1);
  1501. rv = nghttp2_submit_priority(ctx->h2, NGHTTP2_FLAG_NONE,
  1502. stream->stream_id, &pri_spec);
  1503. if(rv)
  1504. goto out;
  1505. }
  1506. rv = nghttp2_session_send(ctx->h2);
  1507. out:
  1508. if(nghttp2_is_fatal(rv)) {
  1509. DEBUGF(LOG_CF(data, cf, "nghttp2_session_send error (%s)%d",
  1510. nghttp2_strerror(rv), rv));
  1511. return CURLE_SEND_ERROR;
  1512. }
  1513. return flush_output(cf, data);
  1514. }
  1515. static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  1516. char *buf, size_t len, CURLcode *err)
  1517. {
  1518. struct cf_h2_ctx *ctx = cf->ctx;
  1519. struct HTTP *stream = data->req.p.http;
  1520. ssize_t nread = -1;
  1521. struct cf_call_data save;
  1522. bool conn_is_closed = FALSE;
  1523. CF_DATA_SAVE(save, cf, data);
  1524. /* If the h2 session has told us to GOAWAY with an error AND
  1525. * indicated the highest stream id it has processes AND
  1526. * the stream we are trying to read has a higher id, this
  1527. * means we will most likely not receive any more for it.
  1528. * Treat this as if the server explicitly had RST the stream */
  1529. if((ctx->goaway && ctx->goaway_error &&
  1530. ctx->last_stream_id > 0 &&
  1531. ctx->last_stream_id < stream->stream_id)) {
  1532. stream->reset = TRUE;
  1533. }
  1534. /* If a stream is RST, it does not matter what state the h2 session
  1535. * is in, our answer to receiving data is always the same. */
  1536. if(stream->reset) {
  1537. *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
  1538. nread = -1;
  1539. goto out;
  1540. }
  1541. if(should_close_session(ctx)) {
  1542. DEBUGF(LOG_CF(data, cf, "http2_recv: nothing to do in this session"));
  1543. if(cf->conn->bits.close) {
  1544. /* already marked for closure, return OK and we're done */
  1545. drained_transfer(cf, data);
  1546. *err = CURLE_OK;
  1547. nread = 0;
  1548. goto out;
  1549. }
  1550. *err = CURLE_HTTP2;
  1551. nread = -1;
  1552. goto out;
  1553. }
  1554. /* Nullify here because we call nghttp2_session_send() and they
  1555. might refer to the old buffer. */
  1556. stream->upload_mem = NULL;
  1557. stream->upload_len = 0;
  1558. /*
  1559. * At this point 'stream' is just in the Curl_easy the connection
  1560. * identifies as its owner at this time.
  1561. */
  1562. if(stream->bodystarted &&
  1563. stream->nread_header_recvbuf < Curl_dyn_len(&stream->header_recvbuf)) {
  1564. /* If there is header data pending for this stream to return, do that */
  1565. size_t left =
  1566. Curl_dyn_len(&stream->header_recvbuf) - stream->nread_header_recvbuf;
  1567. size_t ncopy = CURLMIN(len, left);
  1568. memcpy(buf, Curl_dyn_ptr(&stream->header_recvbuf) +
  1569. stream->nread_header_recvbuf, ncopy);
  1570. stream->nread_header_recvbuf += ncopy;
  1571. DEBUGF(LOG_CF(data, cf, "recv: Got %d bytes from header_recvbuf",
  1572. (int)ncopy));
  1573. nread = ncopy;
  1574. goto out;
  1575. }
  1576. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_recv: win %u/%u",
  1577. stream->stream_id,
  1578. nghttp2_session_get_local_window_size(ctx->h2),
  1579. nghttp2_session_get_stream_local_window_size(ctx->h2,
  1580. stream->stream_id)
  1581. ));
  1582. if(stream->memlen) {
  1583. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv: DRAIN %zu bytes (%p => %p)",
  1584. stream->stream_id, stream->memlen,
  1585. (void *)stream->mem, (void *)buf));
  1586. if(buf != stream->mem) {
  1587. /* if we didn't get the same buffer this time, we must move the data to
  1588. the beginning */
  1589. memmove(buf, stream->mem, stream->memlen);
  1590. stream->len = len - stream->memlen;
  1591. stream->mem = buf;
  1592. }
  1593. if(ctx->pause_stream_id == stream->stream_id && !stream->pausedata) {
  1594. /* We have paused nghttp2, but we have no pause data (see
  1595. on_data_chunk_recv). */
  1596. ctx->pause_stream_id = 0;
  1597. if(h2_process_pending_input(cf, data, err) != 0) {
  1598. nread = -1;
  1599. goto out;
  1600. }
  1601. }
  1602. }
  1603. else if(stream->pausedata) {
  1604. DEBUGASSERT(ctx->pause_stream_id == stream->stream_id);
  1605. nread = CURLMIN(len, stream->pauselen);
  1606. memcpy(buf, stream->pausedata, nread);
  1607. stream->pausedata += nread;
  1608. stream->pauselen -= nread;
  1609. drain_this(cf, data);
  1610. if(stream->pauselen == 0) {
  1611. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] Unpaused", stream->stream_id));
  1612. DEBUGASSERT(ctx->pause_stream_id == stream->stream_id);
  1613. ctx->pause_stream_id = 0;
  1614. stream->pausedata = NULL;
  1615. stream->pauselen = 0;
  1616. }
  1617. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv: returns unpaused %zd bytes",
  1618. stream->stream_id, nread));
  1619. goto out;
  1620. }
  1621. else if(ctx->pause_stream_id) {
  1622. /* If a stream paused nghttp2_session_mem_recv previously, and has
  1623. not processed all data, it still refers to the buffer in
  1624. nghttp2_session. If we call nghttp2_session_mem_recv(), we may
  1625. overwrite that buffer. To avoid that situation, just return
  1626. here with CURLE_AGAIN. This could be busy loop since data in
  1627. socket is not read. But it seems that usually streams are
  1628. notified with its drain property, and socket is read again
  1629. quickly. */
  1630. if(stream->closed) {
  1631. /* closed overrides paused */
  1632. drained_transfer(cf, data);
  1633. nread = 0;
  1634. goto out;
  1635. }
  1636. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] is paused, pause h2sid: %u",
  1637. stream->stream_id, ctx->pause_stream_id));
  1638. *err = CURLE_AGAIN;
  1639. nread = -1;
  1640. goto out;
  1641. }
  1642. else {
  1643. /* We have nothing buffered for `data` and no other stream paused
  1644. * the processing of incoming data, we can therefore read new data
  1645. * from the network.
  1646. * If DATA is coming for this stream, we want to store it ad the
  1647. * `buf` passed in right away - saving us a copy.
  1648. */
  1649. stream->mem = buf;
  1650. stream->len = len;
  1651. stream->memlen = 0;
  1652. if(ctx->inbuflen > 0) {
  1653. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] %zd bytes in inbuf",
  1654. stream->stream_id, ctx->inbuflen - ctx->nread_inbuf));
  1655. if(h2_process_pending_input(cf, data, err))
  1656. return -1;
  1657. }
  1658. while(stream->memlen == 0 && /* have no data for this stream */
  1659. !stream->closed && /* and it is not closed/reset */
  1660. !ctx->pause_stream_id && /* we are not paused either */
  1661. ctx->inbuflen == 0 && /* and out input buffer is empty */
  1662. !conn_is_closed) { /* and connection is not closed */
  1663. /* Receive data from the "lower" filters */
  1664. nread = Curl_conn_cf_recv(cf->next, data, ctx->inbuf, H2_BUFSIZE, err);
  1665. if(nread < 0) {
  1666. DEBUGASSERT(*err);
  1667. if(*err == CURLE_AGAIN) {
  1668. break;
  1669. }
  1670. failf(data, "Failed receiving HTTP2 data");
  1671. conn_is_closed = TRUE;
  1672. }
  1673. else if(nread == 0) {
  1674. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] underlying connection is closed",
  1675. stream->stream_id));
  1676. conn_is_closed = TRUE;
  1677. }
  1678. else {
  1679. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] read %zd from connection",
  1680. stream->stream_id, nread));
  1681. ctx->inbuflen = nread;
  1682. DEBUGASSERT(ctx->nread_inbuf == 0);
  1683. if(h2_process_pending_input(cf, data, err))
  1684. return -1;
  1685. }
  1686. }
  1687. }
  1688. if(stream->memlen) {
  1689. ssize_t retlen = stream->memlen;
  1690. /* TODO: all this buffer handling is very brittle */
  1691. stream->len += stream->memlen;
  1692. stream->memlen = 0;
  1693. if(ctx->pause_stream_id == stream->stream_id) {
  1694. /* data for this stream is returned now, but this stream caused a pause
  1695. already so we need it called again asap */
  1696. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] Data returned for PAUSED stream",
  1697. stream->stream_id));
  1698. drain_this(cf, data);
  1699. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  1700. }
  1701. else if(stream->closed) {
  1702. if(stream->reset || stream->error) {
  1703. nread = http2_handle_stream_close(cf, data, stream, err);
  1704. goto out;
  1705. }
  1706. /* this stream is closed, trigger a another read ASAP to detect that */
  1707. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] is closed now, run again",
  1708. stream->stream_id));
  1709. drain_this(cf, data);
  1710. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  1711. }
  1712. else {
  1713. drained_transfer(cf, data);
  1714. }
  1715. *err = CURLE_OK;
  1716. nread = retlen;
  1717. goto out;
  1718. }
  1719. if(conn_is_closed && !stream->closed) {
  1720. /* underlying connection is closed and we have nothing for the stream.
  1721. * Treat this as a RST */
  1722. stream->closed = stream->reset = TRUE;
  1723. failf(data, "HTTP/2 stream %u was not closed cleanly before"
  1724. " end of the underlying connection",
  1725. stream->stream_id);
  1726. }
  1727. if(stream->closed) {
  1728. nread = http2_handle_stream_close(cf, data, stream, err);
  1729. goto out;
  1730. }
  1731. if(!data->state.drain && Curl_conn_cf_data_pending(cf->next, data)) {
  1732. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] pending data, set drain",
  1733. stream->stream_id));
  1734. drain_this(cf, data);
  1735. }
  1736. *err = CURLE_AGAIN;
  1737. nread = -1;
  1738. out:
  1739. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_recv -> %zd, %d",
  1740. stream->stream_id, nread, *err));
  1741. CF_DATA_RESTORE(cf, save);
  1742. return nread;
  1743. }
  1744. static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  1745. const void *buf, size_t len, CURLcode *err)
  1746. {
  1747. /*
  1748. * Currently, we send request in this function, but this function is also
  1749. * used to send request body. It would be nice to add dedicated function for
  1750. * request.
  1751. */
  1752. struct cf_h2_ctx *ctx = cf->ctx;
  1753. int rv;
  1754. struct HTTP *stream = data->req.p.http;
  1755. nghttp2_nv *nva = NULL;
  1756. size_t nheader;
  1757. nghttp2_data_provider data_prd;
  1758. int32_t stream_id;
  1759. nghttp2_priority_spec pri_spec;
  1760. CURLcode result;
  1761. struct h2h3req *hreq;
  1762. struct cf_call_data save;
  1763. ssize_t nwritten;
  1764. CF_DATA_SAVE(save, cf, data);
  1765. DEBUGF(LOG_CF(data, cf, "cf_send(len=%zu) start", len));
  1766. if(stream->stream_id != -1) {
  1767. if(stream->close_handled) {
  1768. infof(data, "stream %u closed", stream->stream_id);
  1769. *err = CURLE_HTTP2_STREAM;
  1770. nwritten = -1;
  1771. goto out;
  1772. }
  1773. else if(stream->closed) {
  1774. nwritten = http2_handle_stream_close(cf, data, stream, err);
  1775. goto out;
  1776. }
  1777. /* If stream_id != -1, we have dispatched request HEADERS, and now
  1778. are going to send or sending request body in DATA frame */
  1779. stream->upload_mem = buf;
  1780. stream->upload_len = len;
  1781. rv = nghttp2_session_resume_data(ctx->h2, stream->stream_id);
  1782. if(nghttp2_is_fatal(rv)) {
  1783. *err = CURLE_SEND_ERROR;
  1784. nwritten = -1;
  1785. goto out;
  1786. }
  1787. result = h2_session_send(cf, data);
  1788. if(result) {
  1789. *err = result;
  1790. nwritten = -1;
  1791. goto out;
  1792. }
  1793. nwritten = (ssize_t)len - (ssize_t)stream->upload_len;
  1794. stream->upload_mem = NULL;
  1795. stream->upload_len = 0;
  1796. if(should_close_session(ctx)) {
  1797. DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
  1798. *err = CURLE_HTTP2;
  1799. nwritten = -1;
  1800. goto out;
  1801. }
  1802. if(stream->upload_left) {
  1803. /* we are sure that we have more data to send here. Calling the
  1804. following API will make nghttp2_session_want_write() return
  1805. nonzero if remote window allows it, which then libcurl checks
  1806. socket is writable or not. See http2_perform_getsock(). */
  1807. nghttp2_session_resume_data(ctx->h2, stream->stream_id);
  1808. }
  1809. if(!nwritten) {
  1810. size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
  1811. stream->stream_id);
  1812. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_send: win %u/%zu",
  1813. stream->stream_id,
  1814. nghttp2_session_get_remote_window_size(ctx->h2), rwin));
  1815. if(rwin == 0) {
  1816. /* We cannot upload more as the stream's remote window size
  1817. * is 0. We need to receive WIN_UPDATEs before we can continue.
  1818. */
  1819. data->req.keepon |= KEEP_SEND_HOLD;
  1820. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] holding send as remote flow "
  1821. "window is exhausted", stream->stream_id));
  1822. }
  1823. }
  1824. DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_send returns %zd ",
  1825. stream->stream_id, nwritten));
  1826. /* handled writing BODY for open stream. */
  1827. goto out;
  1828. }
  1829. /* Stream has not been opened yet. `buf` is expected to contain
  1830. * request headers. */
  1831. /* TODO: this assumes that the `buf` and `len` we are called with
  1832. * is *all* HEADERs and no body. We have no way to determine here
  1833. * if that is indeed the case. */
  1834. result = Curl_pseudo_headers(data, buf, len, NULL, &hreq);
  1835. if(result) {
  1836. *err = result;
  1837. nwritten = -1;
  1838. goto out;
  1839. }
  1840. nheader = hreq->entries;
  1841. nva = malloc(sizeof(nghttp2_nv) * nheader);
  1842. if(!nva) {
  1843. Curl_pseudo_free(hreq);
  1844. *err = CURLE_OUT_OF_MEMORY;
  1845. nwritten = -1;
  1846. goto out;
  1847. }
  1848. else {
  1849. unsigned int i;
  1850. for(i = 0; i < nheader; i++) {
  1851. nva[i].name = (unsigned char *)hreq->header[i].name;
  1852. nva[i].namelen = hreq->header[i].namelen;
  1853. nva[i].value = (unsigned char *)hreq->header[i].value;
  1854. nva[i].valuelen = hreq->header[i].valuelen;
  1855. nva[i].flags = NGHTTP2_NV_FLAG_NONE;
  1856. }
  1857. Curl_pseudo_free(hreq);
  1858. }
  1859. h2_pri_spec(data, &pri_spec);
  1860. DEBUGF(LOG_CF(data, cf, "send request allowed %d (easy handle %p)",
  1861. nghttp2_session_check_request_allowed(ctx->h2), (void *)data));
  1862. switch(data->state.httpreq) {
  1863. case HTTPREQ_POST:
  1864. case HTTPREQ_POST_FORM:
  1865. case HTTPREQ_POST_MIME:
  1866. case HTTPREQ_PUT:
  1867. if(data->state.infilesize != -1)
  1868. stream->upload_left = data->state.infilesize;
  1869. else
  1870. /* data sending without specifying the data amount up front */
  1871. stream->upload_left = -1; /* unknown, but not zero */
  1872. data_prd.read_callback = data_source_read_callback;
  1873. data_prd.source.ptr = NULL;
  1874. stream_id = nghttp2_submit_request(ctx->h2, &pri_spec, nva, nheader,
  1875. &data_prd, data);
  1876. break;
  1877. default:
  1878. stream_id = nghttp2_submit_request(ctx->h2, &pri_spec, nva, nheader,
  1879. NULL, data);
  1880. }
  1881. Curl_safefree(nva);
  1882. if(stream_id < 0) {
  1883. DEBUGF(LOG_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
  1884. nghttp2_strerror(stream_id), stream_id));
  1885. *err = CURLE_SEND_ERROR;
  1886. nwritten = -1;
  1887. goto out;
  1888. }
  1889. infof(data, "Using Stream ID: %u (easy handle %p)",
  1890. stream_id, (void *)data);
  1891. stream->stream_id = stream_id;
  1892. /* See TODO above. We assume that the whole buf was consumed by
  1893. * generating the request headers. */
  1894. nwritten = len;
  1895. result = h2_session_send(cf, data);
  1896. if(result) {
  1897. *err = result;
  1898. nwritten = -1;
  1899. goto out;
  1900. }
  1901. if(should_close_session(ctx)) {
  1902. DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
  1903. *err = CURLE_HTTP2;
  1904. nwritten = -1;
  1905. goto out;
  1906. }
  1907. /* If whole HEADERS frame was sent off to the underlying socket, the nghttp2
  1908. library calls data_source_read_callback. But only it found that no data
  1909. available, so it deferred the DATA transmission. Which means that
  1910. nghttp2_session_want_write() returns 0 on http2_perform_getsock(), which
  1911. results that no writable socket check is performed. To workaround this,
  1912. we issue nghttp2_session_resume_data() here to bring back DATA
  1913. transmission from deferred state. */
  1914. nghttp2_session_resume_data(ctx->h2, stream->stream_id);
  1915. out:
  1916. CF_DATA_RESTORE(cf, save);
  1917. return nwritten;
  1918. }
  1919. static int cf_h2_get_select_socks(struct Curl_cfilter *cf,
  1920. struct Curl_easy *data,
  1921. curl_socket_t *sock)
  1922. {
  1923. struct cf_h2_ctx *ctx = cf->ctx;
  1924. struct SingleRequest *k = &data->req;
  1925. struct HTTP *stream = data->req.p.http;
  1926. int bitmap = GETSOCK_BLANK;
  1927. struct cf_call_data save;
  1928. CF_DATA_SAVE(save, cf, data);
  1929. sock[0] = Curl_conn_cf_get_socket(cf, data);
  1930. if(!(k->keepon & KEEP_RECV_PAUSE))
  1931. /* Unless paused - in an HTTP/2 connection we can basically always get a
  1932. frame so we should always be ready for one */
  1933. bitmap |= GETSOCK_READSOCK(0);
  1934. /* we're (still uploading OR the HTTP/2 layer wants to send data) AND
  1935. there's a window to send data in */
  1936. if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) ||
  1937. nghttp2_session_want_write(ctx->h2)) &&
  1938. (nghttp2_session_get_remote_window_size(ctx->h2) &&
  1939. nghttp2_session_get_stream_remote_window_size(ctx->h2,
  1940. stream->stream_id)))
  1941. bitmap |= GETSOCK_WRITESOCK(0);
  1942. CF_DATA_RESTORE(cf, save);
  1943. return bitmap;
  1944. }
  1945. static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
  1946. struct Curl_easy *data,
  1947. bool blocking, bool *done)
  1948. {
  1949. struct cf_h2_ctx *ctx = cf->ctx;
  1950. CURLcode result = CURLE_OK;
  1951. struct cf_call_data save;
  1952. if(cf->connected) {
  1953. *done = TRUE;
  1954. return CURLE_OK;
  1955. }
  1956. /* Connect the lower filters first */
  1957. if(!cf->next->connected) {
  1958. result = Curl_conn_cf_connect(cf->next, data, blocking, done);
  1959. if(result || !*done)
  1960. return result;
  1961. }
  1962. *done = FALSE;
  1963. CF_DATA_SAVE(save, cf, data);
  1964. if(!ctx->h2) {
  1965. result = cf_h2_ctx_init(cf, data, FALSE);
  1966. if(result)
  1967. goto out;
  1968. }
  1969. if(-1 == h2_process_pending_input(cf, data, &result)) {
  1970. result = CURLE_HTTP2;
  1971. goto out;
  1972. }
  1973. *done = TRUE;
  1974. cf->connected = TRUE;
  1975. result = CURLE_OK;
  1976. out:
  1977. CF_DATA_RESTORE(cf, save);
  1978. return result;
  1979. }
  1980. static void cf_h2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  1981. {
  1982. struct cf_h2_ctx *ctx = cf->ctx;
  1983. if(ctx) {
  1984. struct cf_call_data save;
  1985. CF_DATA_SAVE(save, cf, data);
  1986. cf_h2_ctx_clear(ctx);
  1987. CF_DATA_RESTORE(cf, save);
  1988. }
  1989. }
  1990. static void cf_h2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
  1991. {
  1992. struct cf_h2_ctx *ctx = cf->ctx;
  1993. (void)data;
  1994. if(ctx) {
  1995. cf_h2_ctx_free(ctx);
  1996. cf->ctx = NULL;
  1997. }
  1998. }
  1999. static CURLcode http2_data_pause(struct Curl_cfilter *cf,
  2000. struct Curl_easy *data,
  2001. bool pause)
  2002. {
  2003. struct cf_h2_ctx *ctx = cf->ctx;
  2004. DEBUGASSERT(data);
  2005. #ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
  2006. if(ctx && ctx->h2) {
  2007. struct HTTP *stream = data->req.p.http;
  2008. uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE;
  2009. CURLcode result;
  2010. int rv = nghttp2_session_set_local_window_size(ctx->h2,
  2011. NGHTTP2_FLAG_NONE,
  2012. stream->stream_id,
  2013. window);
  2014. if(rv) {
  2015. failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
  2016. nghttp2_strerror(rv), rv);
  2017. return CURLE_HTTP2;
  2018. }
  2019. /* make sure the window update gets sent */
  2020. result = h2_session_send(cf, data);
  2021. if(result)
  2022. return result;
  2023. DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u",
  2024. window, stream->stream_id));
  2025. #ifdef DEBUGBUILD
  2026. {
  2027. /* read out the stream local window again */
  2028. uint32_t window2 =
  2029. nghttp2_session_get_stream_local_window_size(ctx->h2,
  2030. stream->stream_id);
  2031. DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u",
  2032. window2, stream->stream_id));
  2033. }
  2034. #endif
  2035. }
  2036. #endif
  2037. return CURLE_OK;
  2038. }
  2039. static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf,
  2040. struct Curl_easy *data,
  2041. int event, int arg1, void *arg2)
  2042. {
  2043. CURLcode result = CURLE_OK;
  2044. struct cf_call_data save;
  2045. (void)arg2;
  2046. CF_DATA_SAVE(save, cf, data);
  2047. switch(event) {
  2048. case CF_CTRL_DATA_SETUP: {
  2049. result = http2_data_setup(cf, data);
  2050. break;
  2051. }
  2052. case CF_CTRL_DATA_PAUSE: {
  2053. result = http2_data_pause(cf, data, (arg1 != 0));
  2054. break;
  2055. }
  2056. case CF_CTRL_DATA_DONE_SEND: {
  2057. result = http2_data_done_send(cf, data);
  2058. break;
  2059. }
  2060. case CF_CTRL_DATA_DONE: {
  2061. http2_data_done(cf, data, arg1 != 0);
  2062. break;
  2063. }
  2064. default:
  2065. break;
  2066. }
  2067. CF_DATA_RESTORE(cf, save);
  2068. return result;
  2069. }
  2070. static bool cf_h2_data_pending(struct Curl_cfilter *cf,
  2071. const struct Curl_easy *data)
  2072. {
  2073. struct cf_h2_ctx *ctx = cf->ctx;
  2074. if(ctx && ctx->inbuflen > 0 && ctx->nread_inbuf > ctx->inbuflen)
  2075. return TRUE;
  2076. return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
  2077. }
  2078. static bool cf_h2_is_alive(struct Curl_cfilter *cf,
  2079. struct Curl_easy *data,
  2080. bool *input_pending)
  2081. {
  2082. struct cf_h2_ctx *ctx = cf->ctx;
  2083. CURLcode result;
  2084. struct cf_call_data save;
  2085. CF_DATA_SAVE(save, cf, data);
  2086. result = (ctx && ctx->h2 && http2_connisalive(cf, data, input_pending));
  2087. DEBUGF(LOG_CF(data, cf, "conn alive -> %d, input_pending=%d",
  2088. result, *input_pending));
  2089. CF_DATA_RESTORE(cf, save);
  2090. return result;
  2091. }
  2092. static CURLcode cf_h2_keep_alive(struct Curl_cfilter *cf,
  2093. struct Curl_easy *data)
  2094. {
  2095. CURLcode result;
  2096. struct cf_call_data save;
  2097. CF_DATA_SAVE(save, cf, data);
  2098. result = http2_send_ping(cf, data);
  2099. CF_DATA_RESTORE(cf, save);
  2100. return result;
  2101. }
  2102. static CURLcode cf_h2_query(struct Curl_cfilter *cf,
  2103. struct Curl_easy *data,
  2104. int query, int *pres1, void *pres2)
  2105. {
  2106. struct cf_h2_ctx *ctx = cf->ctx;
  2107. struct cf_call_data save;
  2108. size_t effective_max;
  2109. switch(query) {
  2110. case CF_QUERY_MAX_CONCURRENT:
  2111. DEBUGASSERT(pres1);
  2112. CF_DATA_SAVE(save, cf, data);
  2113. if(nghttp2_session_check_request_allowed(ctx->h2) == 0) {
  2114. /* the limit is what we have in use right now */
  2115. effective_max = CONN_INUSE(cf->conn);
  2116. }
  2117. else {
  2118. effective_max = ctx->max_concurrent_streams;
  2119. }
  2120. *pres1 = (effective_max > INT_MAX)? INT_MAX : (int)effective_max;
  2121. CF_DATA_RESTORE(cf, save);
  2122. return CURLE_OK;
  2123. default:
  2124. break;
  2125. }
  2126. return cf->next?
  2127. cf->next->cft->query(cf->next, data, query, pres1, pres2) :
  2128. CURLE_UNKNOWN_OPTION;
  2129. }
  2130. struct Curl_cftype Curl_cft_nghttp2 = {
  2131. "HTTP/2",
  2132. CF_TYPE_MULTIPLEX,
  2133. CURL_LOG_DEFAULT,
  2134. cf_h2_destroy,
  2135. cf_h2_connect,
  2136. cf_h2_close,
  2137. Curl_cf_def_get_host,
  2138. cf_h2_get_select_socks,
  2139. cf_h2_data_pending,
  2140. cf_h2_send,
  2141. cf_h2_recv,
  2142. cf_h2_cntrl,
  2143. cf_h2_is_alive,
  2144. cf_h2_keep_alive,
  2145. cf_h2_query,
  2146. };
  2147. static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
  2148. struct Curl_easy *data,
  2149. struct connectdata *conn,
  2150. int sockindex)
  2151. {
  2152. struct Curl_cfilter *cf = NULL;
  2153. struct cf_h2_ctx *ctx;
  2154. CURLcode result = CURLE_OUT_OF_MEMORY;
  2155. DEBUGASSERT(data->conn);
  2156. ctx = calloc(sizeof(*ctx), 1);
  2157. if(!ctx)
  2158. goto out;
  2159. result = Curl_cf_create(&cf, &Curl_cft_nghttp2, ctx);
  2160. if(result)
  2161. goto out;
  2162. Curl_conn_cf_add(data, conn, sockindex, cf);
  2163. result = CURLE_OK;
  2164. out:
  2165. if(result)
  2166. cf_h2_ctx_free(ctx);
  2167. *pcf = result? NULL : cf;
  2168. return result;
  2169. }
  2170. static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf,
  2171. struct Curl_easy *data)
  2172. {
  2173. struct Curl_cfilter *cf_h2 = NULL;
  2174. struct cf_h2_ctx *ctx;
  2175. CURLcode result = CURLE_OUT_OF_MEMORY;
  2176. (void)data;
  2177. ctx = calloc(sizeof(*ctx), 1);
  2178. if(!ctx)
  2179. goto out;
  2180. result = Curl_cf_create(&cf_h2, &Curl_cft_nghttp2, ctx);
  2181. if(result)
  2182. goto out;
  2183. Curl_conn_cf_insert_after(cf, cf_h2);
  2184. result = CURLE_OK;
  2185. out:
  2186. if(result)
  2187. cf_h2_ctx_free(ctx);
  2188. return result;
  2189. }
  2190. bool Curl_cf_is_http2(struct Curl_cfilter *cf, const struct Curl_easy *data)
  2191. {
  2192. (void)data;
  2193. for(; cf; cf = cf->next) {
  2194. if(cf->cft == &Curl_cft_nghttp2)
  2195. return TRUE;
  2196. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  2197. return FALSE;
  2198. }
  2199. return FALSE;
  2200. }
  2201. bool Curl_conn_is_http2(const struct Curl_easy *data,
  2202. const struct connectdata *conn,
  2203. int sockindex)
  2204. {
  2205. return conn? Curl_cf_is_http2(conn->cfilter[sockindex], data) : FALSE;
  2206. }
  2207. bool Curl_http2_may_switch(struct Curl_easy *data,
  2208. struct connectdata *conn,
  2209. int sockindex)
  2210. {
  2211. (void)sockindex;
  2212. if(!Curl_conn_is_http2(data, conn, sockindex) &&
  2213. data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
  2214. #ifndef CURL_DISABLE_PROXY
  2215. if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
  2216. /* We don't support HTTP/2 proxies yet. Also it's debatable
  2217. whether or not this setting should apply to HTTP/2 proxies. */
  2218. infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
  2219. return FALSE;
  2220. }
  2221. #endif
  2222. return TRUE;
  2223. }
  2224. return FALSE;
  2225. }
  2226. CURLcode Curl_http2_switch(struct Curl_easy *data,
  2227. struct connectdata *conn, int sockindex)
  2228. {
  2229. struct Curl_cfilter *cf;
  2230. CURLcode result;
  2231. DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
  2232. DEBUGF(infof(data, DMSGI(data, sockindex, "switching to HTTP/2")));
  2233. result = http2_cfilter_add(&cf, data, conn, sockindex);
  2234. if(result)
  2235. return result;
  2236. result = cf_h2_ctx_init(cf, data, FALSE);
  2237. if(result)
  2238. return result;
  2239. conn->httpversion = 20; /* we know we're on HTTP/2 now */
  2240. conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  2241. conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  2242. multi_connchanged(data->multi);
  2243. if(cf->next) {
  2244. bool done;
  2245. return Curl_conn_cf_connect(cf, data, FALSE, &done);
  2246. }
  2247. return CURLE_OK;
  2248. }
  2249. CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data)
  2250. {
  2251. struct Curl_cfilter *cf_h2;
  2252. CURLcode result;
  2253. DEBUGASSERT(!Curl_cf_is_http2(cf, data));
  2254. result = http2_cfilter_insert_after(cf, data);
  2255. if(result)
  2256. return result;
  2257. cf_h2 = cf->next;
  2258. result = cf_h2_ctx_init(cf_h2, data, FALSE);
  2259. if(result)
  2260. return result;
  2261. cf->conn->httpversion = 20; /* we know we're on HTTP/2 now */
  2262. cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  2263. cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  2264. multi_connchanged(data->multi);
  2265. if(cf_h2->next) {
  2266. bool done;
  2267. return Curl_conn_cf_connect(cf_h2, data, FALSE, &done);
  2268. }
  2269. return CURLE_OK;
  2270. }
  2271. CURLcode Curl_http2_upgrade(struct Curl_easy *data,
  2272. struct connectdata *conn, int sockindex,
  2273. const char *mem, size_t nread)
  2274. {
  2275. struct Curl_cfilter *cf;
  2276. struct cf_h2_ctx *ctx;
  2277. CURLcode result;
  2278. DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
  2279. DEBUGF(infof(data, DMSGI(data, sockindex, "upgrading to HTTP/2")));
  2280. DEBUGASSERT(data->req.upgr101 == UPGR101_RECEIVED);
  2281. result = http2_cfilter_add(&cf, data, conn, sockindex);
  2282. if(result)
  2283. return result;
  2284. DEBUGASSERT(cf->cft == &Curl_cft_nghttp2);
  2285. ctx = cf->ctx;
  2286. result = cf_h2_ctx_init(cf, data, TRUE);
  2287. if(result)
  2288. return result;
  2289. if(nread) {
  2290. /* we are going to copy mem to httpc->inbuf. This is required since
  2291. mem is part of buffer pointed by stream->mem, and callbacks
  2292. called by nghttp2_session_mem_recv() will write stream specific
  2293. data into stream->mem, overwriting data already there. */
  2294. if(H2_BUFSIZE < nread) {
  2295. failf(data, "connection buffer size is too small to store data "
  2296. "following HTTP Upgrade response header: buflen=%d, datalen=%zu",
  2297. H2_BUFSIZE, nread);
  2298. return CURLE_HTTP2;
  2299. }
  2300. infof(data, "Copying HTTP/2 data in stream buffer to connection buffer"
  2301. " after upgrade: len=%zu", nread);
  2302. DEBUGASSERT(ctx->nread_inbuf == 0);
  2303. memcpy(ctx->inbuf, mem, nread);
  2304. ctx->inbuflen = nread;
  2305. }
  2306. conn->httpversion = 20; /* we know we're on HTTP/2 now */
  2307. conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  2308. conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  2309. multi_connchanged(data->multi);
  2310. if(cf->next) {
  2311. bool done;
  2312. return Curl_conn_cf_connect(cf, data, FALSE, &done);
  2313. }
  2314. return CURLE_OK;
  2315. }
  2316. /* Only call this function for a transfer that already got an HTTP/2
  2317. CURLE_HTTP2_STREAM error! */
  2318. bool Curl_h2_http_1_1_error(struct Curl_easy *data)
  2319. {
  2320. struct HTTP *stream = data->req.p.http;
  2321. return (stream && stream->error == NGHTTP2_HTTP_1_1_REQUIRED);
  2322. }
  2323. #else /* !USE_NGHTTP2 */
  2324. /* Satisfy external references even if http2 is not compiled in. */
  2325. #include <curl/curl.h>
  2326. char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
  2327. {
  2328. (void) h;
  2329. (void) num;
  2330. return NULL;
  2331. }
  2332. char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
  2333. {
  2334. (void) h;
  2335. (void) header;
  2336. return NULL;
  2337. }
  2338. #endif /* USE_NGHTTP2 */