c-hyper.c 33 KB

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