c-hyper.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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.haxx.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. /* Curl's integration with Hyper. This replaces certain functions in http.c,
  25. * based on configuration #defines. This implementation supports HTTP/1.1 but
  26. * not HTTP/2.
  27. */
  28. #include "curl_setup.h"
  29. #if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
  30. #ifdef HAVE_NETINET_IN_H
  31. #include <netinet/in.h>
  32. #endif
  33. #ifdef HAVE_NETDB_H
  34. #include <netdb.h>
  35. #endif
  36. #ifdef HAVE_ARPA_INET_H
  37. #include <arpa/inet.h>
  38. #endif
  39. #ifdef HAVE_NET_IF_H
  40. #include <net/if.h>
  41. #endif
  42. #ifdef HAVE_SYS_IOCTL_H
  43. #include <sys/ioctl.h>
  44. #endif
  45. #ifdef HAVE_SYS_PARAM_H
  46. #include <sys/param.h>
  47. #endif
  48. #include <hyper.h>
  49. #include "urldata.h"
  50. #include "cfilters.h"
  51. #include "sendf.h"
  52. #include "headers.h"
  53. #include "transfer.h"
  54. #include "multiif.h"
  55. #include "progress.h"
  56. #include "content_encoding.h"
  57. #include "ws.h"
  58. /* The last 3 #include files should be in this order */
  59. #include "curl_printf.h"
  60. #include "curl_memory.h"
  61. #include "memdebug.h"
  62. static CURLcode cr_hyper_add(struct Curl_easy *data);
  63. typedef enum {
  64. USERDATA_NOT_SET = 0, /* for tasks with no userdata set; must be zero */
  65. USERDATA_RESP_BODY
  66. } userdata_t;
  67. size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
  68. uint8_t *buf, size_t buflen)
  69. {
  70. struct hyp_io_ctx *io_ctx = userp;
  71. struct Curl_easy *data = io_ctx->data;
  72. struct connectdata *conn = data->conn;
  73. CURLcode result;
  74. ssize_t nread;
  75. DEBUGASSERT(conn);
  76. (void)ctx;
  77. DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen));
  78. result = Curl_conn_recv(data, io_ctx->sockindex,
  79. (char *)buf, buflen, &nread);
  80. if(result == CURLE_AGAIN) {
  81. /* would block, register interest */
  82. DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen));
  83. if(data->hyp.read_waker)
  84. hyper_waker_free(data->hyp.read_waker);
  85. data->hyp.read_waker = hyper_context_waker(ctx);
  86. if(!data->hyp.read_waker) {
  87. failf(data, "Couldn't make the read hyper_context_waker");
  88. return HYPER_IO_ERROR;
  89. }
  90. return HYPER_IO_PENDING;
  91. }
  92. else if(result) {
  93. failf(data, "Curl_read failed");
  94. return HYPER_IO_ERROR;
  95. }
  96. DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> %zd", buflen, nread));
  97. return (size_t)nread;
  98. }
  99. size_t Curl_hyper_send(void *userp, hyper_context *ctx,
  100. const uint8_t *buf, size_t buflen)
  101. {
  102. struct hyp_io_ctx *io_ctx = userp;
  103. struct Curl_easy *data = io_ctx->data;
  104. CURLcode result;
  105. size_t nwrote;
  106. DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
  107. result = Curl_conn_send(data, io_ctx->sockindex,
  108. (void *)buf, buflen, FALSE, &nwrote);
  109. if(result == CURLE_AGAIN) {
  110. DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
  111. /* would block, register interest */
  112. if(data->hyp.write_waker)
  113. hyper_waker_free(data->hyp.write_waker);
  114. data->hyp.write_waker = hyper_context_waker(ctx);
  115. if(!data->hyp.write_waker) {
  116. failf(data, "Couldn't make the write hyper_context_waker");
  117. return HYPER_IO_ERROR;
  118. }
  119. return HYPER_IO_PENDING;
  120. }
  121. else if(result) {
  122. failf(data, "Curl_write failed");
  123. return HYPER_IO_ERROR;
  124. }
  125. DEBUGF(infof(data, "Curl_hyper_send(%zu) -> %zd", buflen, nwrote));
  126. return (size_t)nwrote;
  127. }
  128. static int hyper_each_header(void *userdata,
  129. const uint8_t *name,
  130. size_t name_len,
  131. const uint8_t *value,
  132. size_t value_len)
  133. {
  134. struct Curl_easy *data = (struct Curl_easy *)userdata;
  135. size_t len;
  136. char *headp;
  137. CURLcode result;
  138. int writetype;
  139. if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) {
  140. failf(data, "Too long response header");
  141. data->state.hresult = CURLE_TOO_LARGE;
  142. return HYPER_ITER_BREAK;
  143. }
  144. Curl_dyn_reset(&data->state.headerb);
  145. if(name_len) {
  146. if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
  147. (int) name_len, name, (int) value_len, value))
  148. return HYPER_ITER_BREAK;
  149. }
  150. else {
  151. if(Curl_dyn_addn(&data->state.headerb, STRCONST("\r\n")))
  152. return HYPER_ITER_BREAK;
  153. }
  154. len = Curl_dyn_len(&data->state.headerb);
  155. headp = Curl_dyn_ptr(&data->state.headerb);
  156. result = Curl_http_header(data, headp, len);
  157. if(result) {
  158. data->state.hresult = result;
  159. return HYPER_ITER_BREAK;
  160. }
  161. Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
  162. writetype = CLIENTWRITE_HEADER;
  163. if(data->state.hconnect)
  164. writetype |= CLIENTWRITE_CONNECT;
  165. if(data->req.httpcode/100 == 1)
  166. writetype |= CLIENTWRITE_1XX;
  167. result = Curl_client_write(data, writetype, headp, len);
  168. if(result) {
  169. data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
  170. return HYPER_ITER_BREAK;
  171. }
  172. result = Curl_bump_headersize(data, len, FALSE);
  173. if(result) {
  174. data->state.hresult = result;
  175. return HYPER_ITER_BREAK;
  176. }
  177. return HYPER_ITER_CONTINUE;
  178. }
  179. static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
  180. {
  181. char *buf = (char *)hyper_buf_bytes(chunk);
  182. size_t len = hyper_buf_len(chunk);
  183. struct Curl_easy *data = (struct Curl_easy *)userdata;
  184. struct SingleRequest *k = &data->req;
  185. CURLcode result = CURLE_OK;
  186. if(!k->bodywritten) {
  187. #if defined(USE_NTLM)
  188. struct connectdata *conn = data->conn;
  189. if(conn->bits.close &&
  190. (((data->req.httpcode == 401) &&
  191. (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
  192. ((data->req.httpcode == 407) &&
  193. (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
  194. infof(data, "Connection closed while negotiating NTLM");
  195. data->state.authproblem = TRUE;
  196. Curl_safefree(data->req.newurl);
  197. }
  198. #endif
  199. if(Curl_http_exp100_is_selected(data)) {
  200. if(data->req.httpcode < 400) {
  201. Curl_http_exp100_got100(data);
  202. if(data->hyp.send_body_waker) {
  203. hyper_waker_wake(data->hyp.send_body_waker);
  204. data->hyp.send_body_waker = NULL;
  205. }
  206. }
  207. else { /* >= 4xx */
  208. Curl_req_abort_sending(data);
  209. }
  210. }
  211. if(data->state.hconnect && (data->req.httpcode/100 != 2) &&
  212. data->state.authproxy.done) {
  213. data->req.done = TRUE;
  214. result = CURLE_OK;
  215. }
  216. else
  217. result = Curl_http_firstwrite(data);
  218. if(result || data->req.done) {
  219. infof(data, "Return early from hyper_body_chunk");
  220. data->state.hresult = result;
  221. return HYPER_ITER_BREAK;
  222. }
  223. }
  224. result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
  225. if(result) {
  226. data->state.hresult = result;
  227. return HYPER_ITER_BREAK;
  228. }
  229. return HYPER_ITER_CONTINUE;
  230. }
  231. /*
  232. * Hyper does not consider the status line, the first line in an HTTP/1
  233. * response, to be a header. The libcurl API does. This function sends the
  234. * status line in the header callback. */
  235. static CURLcode status_line(struct Curl_easy *data,
  236. struct connectdata *conn,
  237. uint16_t http_status,
  238. int http_version,
  239. const uint8_t *reason, size_t rlen)
  240. {
  241. CURLcode result;
  242. size_t len;
  243. const char *vstr;
  244. int writetype;
  245. vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
  246. (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
  247. /* We need to set 'httpcodeq' for functions that check the response code in
  248. a single place. */
  249. data->req.httpcode = http_status;
  250. data->req.httpversion = http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
  251. (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
  252. if(data->state.hconnect)
  253. /* CONNECT */
  254. data->info.httpproxycode = http_status;
  255. else {
  256. conn->httpversion = (unsigned char)data->req.httpversion;
  257. if(http_version == HYPER_HTTP_VERSION_1_0)
  258. data->state.httpwant = CURL_HTTP_VERSION_1_0;
  259. result = Curl_http_statusline(data, conn);
  260. if(result)
  261. return result;
  262. }
  263. Curl_dyn_reset(&data->state.headerb);
  264. result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n",
  265. vstr,
  266. (int)http_status,
  267. (int)rlen, reason);
  268. if(result)
  269. return result;
  270. len = Curl_dyn_len(&data->state.headerb);
  271. Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
  272. len);
  273. writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
  274. if(data->state.hconnect)
  275. writetype |= CLIENTWRITE_CONNECT;
  276. result = Curl_client_write(data, writetype,
  277. Curl_dyn_ptr(&data->state.headerb), len);
  278. if(result)
  279. return result;
  280. result = Curl_bump_headersize(data, len, FALSE);
  281. return result;
  282. }
  283. /*
  284. * Hyper does not pass on the last empty response header. The libcurl API
  285. * does. This function sends an empty header in the header callback.
  286. */
  287. static CURLcode empty_header(struct Curl_easy *data)
  288. {
  289. CURLcode result = Curl_http_size(data);
  290. if(!result) {
  291. result = hyper_each_header(data, NULL, 0, NULL, 0) ?
  292. CURLE_WRITE_ERROR : CURLE_OK;
  293. if(result)
  294. failf(data, "hyperstream: could not pass blank header");
  295. /* Hyper does chunked decoding itself. If it was added during
  296. * response header processing, remove it again. */
  297. Curl_cwriter_remove_by_name(data, "chunked");
  298. }
  299. return result;
  300. }
  301. CURLcode Curl_hyper_stream(struct Curl_easy *data,
  302. struct connectdata *conn,
  303. int *didwhat,
  304. int select_res)
  305. {
  306. hyper_response *resp = NULL;
  307. uint16_t http_status;
  308. int http_version;
  309. hyper_headers *headers = NULL;
  310. hyper_body *resp_body = NULL;
  311. struct hyptransfer *h = &data->hyp;
  312. hyper_task *task;
  313. hyper_task *foreach;
  314. const uint8_t *reasonp;
  315. size_t reason_len;
  316. CURLcode result = CURLE_OK;
  317. struct SingleRequest *k = &data->req;
  318. (void)conn;
  319. if(data->hyp.send_body_waker) {
  320. /* If there is still something to upload, wake it to give it
  321. * another try. */
  322. hyper_waker_wake(data->hyp.send_body_waker);
  323. data->hyp.send_body_waker = NULL;
  324. }
  325. if(select_res & CURL_CSELECT_IN) {
  326. if(h->read_waker)
  327. hyper_waker_wake(h->read_waker);
  328. h->read_waker = NULL;
  329. }
  330. if(select_res & CURL_CSELECT_OUT) {
  331. if(h->write_waker)
  332. hyper_waker_wake(h->write_waker);
  333. h->write_waker = NULL;
  334. }
  335. while(1) {
  336. hyper_task_return_type t;
  337. task = hyper_executor_poll(h->exec);
  338. if(!task) {
  339. *didwhat = KEEP_RECV;
  340. break;
  341. }
  342. t = hyper_task_type(task);
  343. if(t == HYPER_TASK_ERROR) {
  344. hyper_error *hypererr = hyper_task_value(task);
  345. hyper_task_free(task);
  346. if(data->state.hresult) {
  347. /* override Hyper's view, might not even be an error */
  348. result = data->state.hresult;
  349. infof(data, "hyperstream is done (by early callback)");
  350. }
  351. else {
  352. uint8_t errbuf[256];
  353. size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
  354. hyper_code code = hyper_error_code(hypererr);
  355. failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
  356. switch(code) {
  357. case HYPERE_ABORTED_BY_CALLBACK:
  358. result = CURLE_OK;
  359. goto out;
  360. case HYPERE_UNEXPECTED_EOF:
  361. if(!data->req.bytecount)
  362. result = CURLE_GOT_NOTHING;
  363. else
  364. result = CURLE_RECV_ERROR;
  365. goto out;
  366. case HYPERE_INVALID_PEER_MESSAGE:
  367. /* bump headerbytecount to avoid the count remaining at zero and
  368. appearing to not having read anything from the peer at all */
  369. data->req.headerbytecount++;
  370. result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
  371. goto out;
  372. default:
  373. result = CURLE_RECV_ERROR;
  374. goto out;
  375. }
  376. }
  377. data->req.done = TRUE;
  378. hyper_error_free(hypererr);
  379. break;
  380. }
  381. else if(t == HYPER_TASK_EMPTY) {
  382. void *userdata = hyper_task_userdata(task);
  383. hyper_task_free(task);
  384. if(userdata == (void *)USERDATA_RESP_BODY) {
  385. /* end of transfer */
  386. data->req.done = TRUE;
  387. infof(data, "hyperstream is done");
  388. if(!k->bodywritten) {
  389. /* hyper does not always call the body write callback */
  390. result = Curl_http_firstwrite(data);
  391. }
  392. break;
  393. }
  394. else {
  395. /* A background task for hyper; ignore */
  396. DEBUGF(infof(data, "hyper: some background task done"));
  397. continue;
  398. }
  399. }
  400. else if(t == HYPER_TASK_RESPONSE) {
  401. resp = hyper_task_value(task);
  402. hyper_task_free(task);
  403. *didwhat = KEEP_RECV;
  404. if(!resp) {
  405. failf(data, "hyperstream: could not get response");
  406. result = CURLE_RECV_ERROR;
  407. goto out;
  408. }
  409. http_status = hyper_response_status(resp);
  410. http_version = hyper_response_version(resp);
  411. reasonp = hyper_response_reason_phrase(resp);
  412. reason_len = hyper_response_reason_phrase_len(resp);
  413. if(http_status == 417 && Curl_http_exp100_is_selected(data)) {
  414. infof(data, "Got 417 while waiting for a 100");
  415. data->state.disableexpect = TRUE;
  416. data->req.newurl = strdup(data->state.url);
  417. Curl_req_abort_sending(data);
  418. }
  419. result = status_line(data, conn,
  420. http_status, http_version, reasonp, reason_len);
  421. if(result)
  422. goto out;
  423. headers = hyper_response_headers(resp);
  424. if(!headers) {
  425. failf(data, "hyperstream: could not get response headers");
  426. result = CURLE_RECV_ERROR;
  427. goto out;
  428. }
  429. /* the headers are already received */
  430. hyper_headers_foreach(headers, hyper_each_header, data);
  431. if(data->state.hresult) {
  432. result = data->state.hresult;
  433. goto out;
  434. }
  435. result = empty_header(data);
  436. if(result)
  437. goto out;
  438. k->deductheadercount =
  439. (100 <= http_status && 199 >= http_status) ? k->headerbytecount : 0;
  440. #ifndef CURL_DISABLE_WEBSOCKETS
  441. if(k->upgr101 == UPGR101_WS) {
  442. if(http_status == 101) {
  443. /* verify the response */
  444. result = Curl_ws_accept(data, NULL, 0);
  445. if(result)
  446. goto out;
  447. }
  448. else {
  449. failf(data, "Expected 101, got %u", k->httpcode);
  450. result = CURLE_HTTP_RETURNED_ERROR;
  451. goto out;
  452. }
  453. }
  454. #endif
  455. /* Curl_http_auth_act() checks what authentication methods that are
  456. * available and decides which one (if any) to use. It will set 'newurl'
  457. * if an auth method was picked. */
  458. result = Curl_http_auth_act(data);
  459. if(result)
  460. goto out;
  461. resp_body = hyper_response_body(resp);
  462. if(!resp_body) {
  463. failf(data, "hyperstream: could not get response body");
  464. result = CURLE_RECV_ERROR;
  465. goto out;
  466. }
  467. foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
  468. if(!foreach) {
  469. failf(data, "hyperstream: body foreach failed");
  470. result = CURLE_OUT_OF_MEMORY;
  471. goto out;
  472. }
  473. hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY);
  474. if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
  475. failf(data, "Couldn't hyper_executor_push the body-foreach");
  476. result = CURLE_OUT_OF_MEMORY;
  477. goto out;
  478. }
  479. hyper_response_free(resp);
  480. resp = NULL;
  481. }
  482. else {
  483. DEBUGF(infof(data, "hyper: unhandled tasktype %x", t));
  484. }
  485. } /* while(1) */
  486. if(!result && Curl_xfer_needs_flush(data)) {
  487. DEBUGF(infof(data, "Curl_hyper_stream(), connection needs flush"));
  488. result = Curl_xfer_flush(data);
  489. }
  490. out:
  491. DEBUGF(infof(data, "Curl_hyper_stream() -> %d", result));
  492. if(resp)
  493. hyper_response_free(resp);
  494. return result;
  495. }
  496. static CURLcode debug_request(struct Curl_easy *data,
  497. const char *method,
  498. const char *path)
  499. {
  500. char *req = aprintf("%s %s HTTP/1.1\r\n", method, path);
  501. if(!req)
  502. return CURLE_OUT_OF_MEMORY;
  503. Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
  504. free(req);
  505. return CURLE_OK;
  506. }
  507. /*
  508. * Given a full header line "name: value" (optional CRLF in the input, should
  509. * be in the output), add to Hyper and send to the debug callback.
  510. *
  511. * Supports multiple headers.
  512. */
  513. CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
  514. const char *line)
  515. {
  516. const char *p;
  517. const char *n;
  518. size_t nlen;
  519. const char *v;
  520. size_t vlen;
  521. bool newline = TRUE;
  522. int numh = 0;
  523. if(!line)
  524. return CURLE_OK;
  525. n = line;
  526. do {
  527. size_t linelen = 0;
  528. p = strchr(n, ':');
  529. if(!p)
  530. /* this is fine if we already added at least one header */
  531. return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
  532. nlen = p - n;
  533. p++; /* move past the colon */
  534. while(*p == ' ')
  535. p++;
  536. v = p;
  537. p = strchr(v, '\r');
  538. if(!p) {
  539. p = strchr(v, '\n');
  540. if(p)
  541. linelen = 1; /* LF only */
  542. else {
  543. p = strchr(v, '\0');
  544. newline = FALSE; /* no newline */
  545. }
  546. }
  547. else
  548. linelen = 2; /* CRLF ending */
  549. linelen += (p - n);
  550. vlen = p - v;
  551. if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
  552. (uint8_t *)v, vlen)) {
  553. failf(data, "hyper refused to add header '%s'", line);
  554. return CURLE_OUT_OF_MEMORY;
  555. }
  556. if(data->set.verbose) {
  557. char *ptr = NULL;
  558. if(!newline) {
  559. ptr = aprintf("%.*s\r\n", (int)linelen, line);
  560. if(!ptr)
  561. return CURLE_OUT_OF_MEMORY;
  562. Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2);
  563. free(ptr);
  564. }
  565. else
  566. Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen);
  567. }
  568. numh++;
  569. n += linelen;
  570. } while(newline);
  571. return CURLE_OK;
  572. }
  573. static CURLcode request_target(struct Curl_easy *data,
  574. struct connectdata *conn,
  575. const char *method,
  576. hyper_request *req)
  577. {
  578. CURLcode result;
  579. struct dynbuf r;
  580. Curl_dyn_init(&r, DYN_HTTP_REQUEST);
  581. result = Curl_http_target(data, conn, &r);
  582. if(result)
  583. return result;
  584. if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
  585. Curl_dyn_len(&r))) {
  586. failf(data, "error setting uri to hyper");
  587. result = CURLE_OUT_OF_MEMORY;
  588. }
  589. else
  590. result = debug_request(data, method, Curl_dyn_ptr(&r));
  591. Curl_dyn_free(&r);
  592. return result;
  593. }
  594. static int uploadstreamed(void *userdata, hyper_context *ctx,
  595. hyper_buf **chunk)
  596. {
  597. size_t fillcount;
  598. struct Curl_easy *data = (struct Curl_easy *)userdata;
  599. CURLcode result;
  600. char *xfer_ulbuf;
  601. size_t xfer_ulblen;
  602. bool eos;
  603. int rc = HYPER_POLL_ERROR;
  604. (void)ctx;
  605. result = Curl_multi_xfer_ulbuf_borrow(data, &xfer_ulbuf, &xfer_ulblen);
  606. if(result)
  607. goto out;
  608. result = Curl_client_read(data, xfer_ulbuf, xfer_ulblen, &fillcount, &eos);
  609. if(result)
  610. goto out;
  611. if(fillcount) {
  612. hyper_buf *copy = hyper_buf_copy((uint8_t *)xfer_ulbuf, fillcount);
  613. if(copy)
  614. *chunk = copy;
  615. else {
  616. result = CURLE_OUT_OF_MEMORY;
  617. goto out;
  618. }
  619. /* increasing the writebytecount here is a little premature but we
  620. do not know exactly when the body is sent */
  621. data->req.writebytecount += fillcount;
  622. if(eos)
  623. data->req.eos_read = TRUE;
  624. Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
  625. rc = HYPER_POLL_READY;
  626. }
  627. else if(eos) {
  628. data->req.eos_read = TRUE;
  629. *chunk = NULL;
  630. rc = HYPER_POLL_READY;
  631. }
  632. else {
  633. /* paused, save a waker */
  634. if(data->hyp.send_body_waker)
  635. hyper_waker_free(data->hyp.send_body_waker);
  636. data->hyp.send_body_waker = hyper_context_waker(ctx);
  637. rc = HYPER_POLL_PENDING;
  638. }
  639. if(!data->req.upload_done && data->req.eos_read) {
  640. DEBUGF(infof(data, "hyper: uploadstreamed(), upload is done"));
  641. result = Curl_req_set_upload_done(data);
  642. }
  643. out:
  644. Curl_multi_xfer_ulbuf_release(data, xfer_ulbuf);
  645. data->state.hresult = result;
  646. DEBUGF(infof(data, "hyper: uploadstreamed() -> %d", result));
  647. return rc;
  648. }
  649. /*
  650. * finalize_request() sets up last headers and optional body settings
  651. */
  652. static CURLcode finalize_request(struct Curl_easy *data,
  653. hyper_headers *headers,
  654. hyper_request *hyperreq,
  655. Curl_HttpReq httpreq)
  656. {
  657. CURLcode result = CURLE_OK;
  658. struct dynbuf req;
  659. if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
  660. Curl_pgrsSetUploadSize(data, 0); /* no request body */
  661. }
  662. else {
  663. hyper_body *body;
  664. Curl_dyn_init(&req, DYN_HTTP_REQUEST);
  665. result = Curl_http_req_complete(data, &req, httpreq);
  666. if(result)
  667. return result;
  668. /* if the "complete" above did produce more than the closing line,
  669. parse the added headers */
  670. if(Curl_dyn_len(&req) != 2 || strcmp(Curl_dyn_ptr(&req), "\r\n")) {
  671. result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
  672. if(result)
  673. return result;
  674. }
  675. Curl_dyn_free(&req);
  676. body = hyper_body_new();
  677. hyper_body_set_userdata(body, data);
  678. hyper_body_set_data_func(body, uploadstreamed);
  679. if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
  680. /* fail */
  681. result = CURLE_OUT_OF_MEMORY;
  682. }
  683. }
  684. return cr_hyper_add(data);
  685. }
  686. static CURLcode cookies(struct Curl_easy *data,
  687. struct connectdata *conn,
  688. hyper_headers *headers)
  689. {
  690. struct dynbuf req;
  691. CURLcode result;
  692. Curl_dyn_init(&req, DYN_HTTP_REQUEST);
  693. result = Curl_http_cookies(data, conn, &req);
  694. if(!result)
  695. result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
  696. Curl_dyn_free(&req);
  697. return result;
  698. }
  699. /* called on 1xx responses */
  700. static void http1xx_cb(void *arg, struct hyper_response *resp)
  701. {
  702. struct Curl_easy *data = (struct Curl_easy *)arg;
  703. hyper_headers *headers = NULL;
  704. CURLcode result = CURLE_OK;
  705. uint16_t http_status;
  706. int http_version;
  707. const uint8_t *reasonp;
  708. size_t reason_len;
  709. infof(data, "Got HTTP 1xx informational");
  710. http_status = hyper_response_status(resp);
  711. http_version = hyper_response_version(resp);
  712. reasonp = hyper_response_reason_phrase(resp);
  713. reason_len = hyper_response_reason_phrase_len(resp);
  714. result = status_line(data, data->conn,
  715. http_status, http_version, reasonp, reason_len);
  716. if(!result) {
  717. headers = hyper_response_headers(resp);
  718. if(!headers) {
  719. failf(data, "hyperstream: could not get 1xx response headers");
  720. result = CURLE_RECV_ERROR;
  721. }
  722. }
  723. data->state.hresult = result;
  724. if(!result) {
  725. /* the headers are already received */
  726. hyper_headers_foreach(headers, hyper_each_header, data);
  727. /* this callback also sets data->state.hresult on error */
  728. if(empty_header(data))
  729. result = CURLE_OUT_OF_MEMORY;
  730. }
  731. if(data->state.hresult)
  732. infof(data, "ERROR in 1xx, bail out");
  733. }
  734. /*
  735. * Curl_http() gets called from the generic multi_do() function when an HTTP
  736. * request is to be performed. This creates and sends a properly constructed
  737. * HTTP request.
  738. */
  739. CURLcode Curl_http(struct Curl_easy *data, bool *done)
  740. {
  741. struct connectdata *conn = data->conn;
  742. struct hyptransfer *h = &data->hyp;
  743. hyper_io *io = NULL;
  744. hyper_clientconn_options *options = NULL;
  745. hyper_task *task = NULL; /* for the handshake */
  746. hyper_task *sendtask = NULL; /* for the send */
  747. hyper_clientconn *client = NULL;
  748. hyper_request *req = NULL;
  749. hyper_headers *headers = NULL;
  750. hyper_task *handshake = NULL;
  751. CURLcode result;
  752. const char *p_accept; /* Accept: string */
  753. const char *method;
  754. Curl_HttpReq httpreq;
  755. const char *te = NULL; /* transfer-encoding */
  756. hyper_code rc;
  757. /* Always consider the DO phase done after this function call, even if there
  758. may be parts of the request that is not yet sent, since we can deal with
  759. the rest of the request in the PERFORM phase. */
  760. *done = TRUE;
  761. result = Curl_client_start(data);
  762. if(result)
  763. goto out;
  764. /* Add collecting of headers written to client. For a new connection,
  765. * we might have done that already, but reuse
  766. * or multiplex needs it here as well. */
  767. result = Curl_headers_init(data);
  768. if(result)
  769. goto out;
  770. infof(data, "Time for the Hyper dance");
  771. memset(h, 0, sizeof(struct hyptransfer));
  772. result = Curl_http_host(data, conn);
  773. if(result)
  774. goto out;
  775. Curl_http_method(data, conn, &method, &httpreq);
  776. DEBUGASSERT(data->req.bytecount == 0);
  777. /* setup the authentication headers */
  778. {
  779. char *pq = NULL;
  780. if(data->state.up.query) {
  781. pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
  782. if(!pq) {
  783. result = CURLE_OUT_OF_MEMORY;
  784. goto out;
  785. }
  786. }
  787. result = Curl_http_output_auth(data, conn, method, httpreq,
  788. (pq ? pq : data->state.up.path), FALSE);
  789. free(pq);
  790. if(result)
  791. goto out;
  792. }
  793. result = Curl_http_req_set_reader(data, httpreq, &te);
  794. if(result)
  795. goto out;
  796. result = Curl_http_range(data, httpreq);
  797. if(result)
  798. goto out;
  799. result = Curl_http_useragent(data);
  800. if(result)
  801. goto out;
  802. io = hyper_io_new();
  803. if(!io) {
  804. failf(data, "Couldn't create hyper IO");
  805. result = CURLE_OUT_OF_MEMORY;
  806. goto out;
  807. }
  808. /* tell Hyper how to read/write network data */
  809. h->io_ctx.data = data;
  810. h->io_ctx.sockindex = FIRSTSOCKET;
  811. hyper_io_set_userdata(io, &h->io_ctx);
  812. hyper_io_set_read(io, Curl_hyper_recv);
  813. hyper_io_set_write(io, Curl_hyper_send);
  814. /* create an executor to poll futures */
  815. if(!h->exec) {
  816. h->exec = hyper_executor_new();
  817. if(!h->exec) {
  818. failf(data, "Couldn't create hyper executor");
  819. result = CURLE_OUT_OF_MEMORY;
  820. goto out;
  821. }
  822. }
  823. options = hyper_clientconn_options_new();
  824. if(!options) {
  825. failf(data, "Couldn't create hyper client options");
  826. result = CURLE_OUT_OF_MEMORY;
  827. goto out;
  828. }
  829. if(conn->alpn == CURL_HTTP_VERSION_2) {
  830. failf(data, "ALPN protocol h2 not supported with Hyper");
  831. result = CURLE_UNSUPPORTED_PROTOCOL;
  832. goto out;
  833. }
  834. hyper_clientconn_options_set_preserve_header_case(options, 1);
  835. hyper_clientconn_options_set_preserve_header_order(options, 1);
  836. hyper_clientconn_options_http1_allow_multiline_headers(options, 1);
  837. hyper_clientconn_options_exec(options, h->exec);
  838. /* "Both the `io` and the `options` are consumed in this function call" */
  839. handshake = hyper_clientconn_handshake(io, options);
  840. if(!handshake) {
  841. failf(data, "Couldn't create hyper client handshake");
  842. result = CURLE_OUT_OF_MEMORY;
  843. goto out;
  844. }
  845. io = NULL;
  846. options = NULL;
  847. if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
  848. failf(data, "Couldn't hyper_executor_push the handshake");
  849. result = CURLE_OUT_OF_MEMORY;
  850. goto out;
  851. }
  852. handshake = NULL; /* ownership passed on */
  853. task = hyper_executor_poll(h->exec);
  854. if(!task) {
  855. failf(data, "Couldn't hyper_executor_poll the handshake");
  856. result = CURLE_OUT_OF_MEMORY;
  857. goto out;
  858. }
  859. client = hyper_task_value(task);
  860. hyper_task_free(task);
  861. req = hyper_request_new();
  862. if(!req) {
  863. failf(data, "Couldn't hyper_request_new");
  864. result = CURLE_OUT_OF_MEMORY;
  865. goto out;
  866. }
  867. if(!Curl_use_http_1_1plus(data, conn)) {
  868. if(HYPERE_OK != hyper_request_set_version(req,
  869. HYPER_HTTP_VERSION_1_0)) {
  870. failf(data, "error setting HTTP version");
  871. result = CURLE_OUT_OF_MEMORY;
  872. goto out;
  873. }
  874. }
  875. if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
  876. failf(data, "error setting method");
  877. result = CURLE_OUT_OF_MEMORY;
  878. goto out;
  879. }
  880. result = request_target(data, conn, method, req);
  881. if(result)
  882. goto out;
  883. headers = hyper_request_headers(req);
  884. if(!headers) {
  885. failf(data, "hyper_request_headers");
  886. result = CURLE_OUT_OF_MEMORY;
  887. goto out;
  888. }
  889. rc = hyper_request_on_informational(req, http1xx_cb, data);
  890. if(rc) {
  891. result = CURLE_OUT_OF_MEMORY;
  892. goto out;
  893. }
  894. if(data->state.aptr.host) {
  895. result = Curl_hyper_header(data, headers, data->state.aptr.host);
  896. if(result)
  897. goto out;
  898. }
  899. #ifndef CURL_DISABLE_PROXY
  900. if(data->state.aptr.proxyuserpwd) {
  901. result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd);
  902. if(result)
  903. goto out;
  904. }
  905. #endif
  906. if(data->state.aptr.userpwd) {
  907. result = Curl_hyper_header(data, headers, data->state.aptr.userpwd);
  908. if(result)
  909. goto out;
  910. }
  911. if((data->state.use_range && data->state.aptr.rangeline)) {
  912. result = Curl_hyper_header(data, headers, data->state.aptr.rangeline);
  913. if(result)
  914. goto out;
  915. }
  916. if(data->set.str[STRING_USERAGENT] &&
  917. *data->set.str[STRING_USERAGENT] &&
  918. data->state.aptr.uagent) {
  919. result = Curl_hyper_header(data, headers, data->state.aptr.uagent);
  920. if(result)
  921. goto out;
  922. }
  923. p_accept = Curl_checkheaders(data,
  924. STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
  925. if(p_accept) {
  926. result = Curl_hyper_header(data, headers, p_accept);
  927. if(result)
  928. goto out;
  929. }
  930. if(te) {
  931. result = Curl_hyper_header(data, headers, te);
  932. if(result)
  933. goto out;
  934. }
  935. #ifndef CURL_DISABLE_ALTSVC
  936. if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
  937. char *altused = aprintf("Alt-Used: %s:%d\r\n",
  938. conn->conn_to_host.name, conn->conn_to_port);
  939. if(!altused) {
  940. result = CURLE_OUT_OF_MEMORY;
  941. goto out;
  942. }
  943. result = Curl_hyper_header(data, headers, altused);
  944. if(result)
  945. goto out;
  946. free(altused);
  947. }
  948. #endif
  949. #ifndef CURL_DISABLE_PROXY
  950. if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
  951. !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
  952. !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
  953. result = Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive");
  954. if(result)
  955. goto out;
  956. }
  957. #endif
  958. Curl_safefree(data->state.aptr.ref);
  959. if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
  960. data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
  961. if(!data->state.aptr.ref)
  962. result = CURLE_OUT_OF_MEMORY;
  963. else
  964. result = Curl_hyper_header(data, headers, data->state.aptr.ref);
  965. if(result)
  966. goto out;
  967. }
  968. #ifdef HAVE_LIBZ
  969. /* we only consider transfer-encoding magic if libz support is built-in */
  970. result = Curl_transferencode(data);
  971. if(result)
  972. goto out;
  973. result = Curl_hyper_header(data, headers, data->state.aptr.te);
  974. if(result)
  975. goto out;
  976. #endif
  977. if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
  978. data->set.str[STRING_ENCODING]) {
  979. Curl_safefree(data->state.aptr.accept_encoding);
  980. data->state.aptr.accept_encoding =
  981. aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
  982. if(!data->state.aptr.accept_encoding)
  983. result = CURLE_OUT_OF_MEMORY;
  984. else
  985. result = Curl_hyper_header(data, headers,
  986. data->state.aptr.accept_encoding);
  987. if(result)
  988. goto out;
  989. }
  990. else
  991. Curl_safefree(data->state.aptr.accept_encoding);
  992. result = cookies(data, conn, headers);
  993. if(result)
  994. goto out;
  995. if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
  996. result = Curl_ws_request(data, headers);
  997. result = Curl_add_timecondition(data, headers);
  998. if(result)
  999. goto out;
  1000. result = Curl_add_custom_headers(data, FALSE, headers);
  1001. if(result)
  1002. goto out;
  1003. result = finalize_request(data, headers, req, httpreq);
  1004. if(result)
  1005. goto out;
  1006. Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
  1007. if(data->req.upload_chunky && data->req.authneg) {
  1008. data->req.upload_chunky = TRUE;
  1009. }
  1010. else {
  1011. data->req.upload_chunky = FALSE;
  1012. }
  1013. sendtask = hyper_clientconn_send(client, req);
  1014. if(!sendtask) {
  1015. failf(data, "hyper_clientconn_send");
  1016. result = CURLE_OUT_OF_MEMORY;
  1017. goto out;
  1018. }
  1019. req = NULL;
  1020. if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
  1021. failf(data, "Couldn't hyper_executor_push the send");
  1022. result = CURLE_OUT_OF_MEMORY;
  1023. goto out;
  1024. }
  1025. sendtask = NULL; /* ownership passed on */
  1026. hyper_clientconn_free(client);
  1027. client = NULL;
  1028. if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
  1029. /* HTTP GET/HEAD download */
  1030. Curl_pgrsSetUploadSize(data, 0); /* nothing */
  1031. result = Curl_req_set_upload_done(data);
  1032. if(result)
  1033. goto out;
  1034. }
  1035. Curl_xfer_setup1(data, CURL_XFER_SENDRECV, -1, TRUE);
  1036. conn->datastream = Curl_hyper_stream;
  1037. /* clear userpwd and proxyuserpwd to avoid reusing old credentials
  1038. * from reused connections */
  1039. Curl_safefree(data->state.aptr.userpwd);
  1040. #ifndef CURL_DISABLE_PROXY
  1041. Curl_safefree(data->state.aptr.proxyuserpwd);
  1042. #endif
  1043. out:
  1044. if(result) {
  1045. if(io)
  1046. hyper_io_free(io);
  1047. if(options)
  1048. hyper_clientconn_options_free(options);
  1049. if(handshake)
  1050. hyper_task_free(handshake);
  1051. if(client)
  1052. hyper_clientconn_free(client);
  1053. if(req)
  1054. hyper_request_free(req);
  1055. }
  1056. return result;
  1057. }
  1058. void Curl_hyper_done(struct Curl_easy *data)
  1059. {
  1060. struct hyptransfer *h = &data->hyp;
  1061. if(h->exec) {
  1062. hyper_executor_free(h->exec);
  1063. h->exec = NULL;
  1064. }
  1065. if(h->read_waker) {
  1066. hyper_waker_free(h->read_waker);
  1067. h->read_waker = NULL;
  1068. }
  1069. if(h->write_waker) {
  1070. hyper_waker_free(h->write_waker);
  1071. h->write_waker = NULL;
  1072. }
  1073. if(h->send_body_waker) {
  1074. hyper_waker_free(h->send_body_waker);
  1075. h->send_body_waker = NULL;
  1076. }
  1077. }
  1078. static CURLcode cr_hyper_unpause(struct Curl_easy *data,
  1079. struct Curl_creader *reader)
  1080. {
  1081. (void)reader;
  1082. if(data->hyp.send_body_waker) {
  1083. hyper_waker_wake(data->hyp.send_body_waker);
  1084. data->hyp.send_body_waker = NULL;
  1085. }
  1086. return CURLE_OK;
  1087. }
  1088. /* Hyper client reader, handling unpausing */
  1089. static const struct Curl_crtype cr_hyper_protocol = {
  1090. "cr-hyper",
  1091. Curl_creader_def_init,
  1092. Curl_creader_def_read,
  1093. Curl_creader_def_close,
  1094. Curl_creader_def_needs_rewind,
  1095. Curl_creader_def_total_length,
  1096. Curl_creader_def_resume_from,
  1097. Curl_creader_def_rewind,
  1098. cr_hyper_unpause,
  1099. Curl_creader_def_is_paused,
  1100. Curl_creader_def_done,
  1101. sizeof(struct Curl_creader)
  1102. };
  1103. static CURLcode cr_hyper_add(struct Curl_easy *data)
  1104. {
  1105. struct Curl_creader *reader = NULL;
  1106. CURLcode result;
  1107. result = Curl_creader_create(&reader, data, &cr_hyper_protocol,
  1108. CURL_CR_PROTOCOL);
  1109. if(!result)
  1110. result = Curl_creader_add(data, reader);
  1111. if(result && reader)
  1112. Curl_creader_free(data, reader);
  1113. return result;
  1114. }
  1115. #endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */