cfilters.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  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. #include "urldata.h"
  26. #include "strerror.h"
  27. #include "cfilters.h"
  28. #include "connect.h"
  29. #include "url.h"
  30. #include "sendf.h"
  31. #include "sockaddr.h" /* required for Curl_sockaddr_storage */
  32. #include "multiif.h"
  33. #include "progress.h"
  34. #include "select.h"
  35. #include "curlx/warnless.h"
  36. #include "curlx/strparse.h"
  37. /* The last 2 #include files should be in this order */
  38. #include "curl_memory.h"
  39. #include "memdebug.h"
  40. static void cf_cntrl_update_info(struct Curl_easy *data,
  41. struct connectdata *conn);
  42. #ifdef UNITTESTS
  43. /* used by unit2600.c */
  44. void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  45. {
  46. cf->connected = FALSE;
  47. if(cf->next)
  48. cf->next->cft->do_close(cf->next, data);
  49. }
  50. #endif
  51. CURLcode Curl_cf_def_shutdown(struct Curl_cfilter *cf,
  52. struct Curl_easy *data, bool *done)
  53. {
  54. (void)cf;
  55. (void)data;
  56. *done = TRUE;
  57. return CURLE_OK;
  58. }
  59. static void conn_report_connect_stats(struct Curl_easy *data,
  60. struct connectdata *conn);
  61. CURLcode Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
  62. struct Curl_easy *data,
  63. struct easy_pollset *ps)
  64. {
  65. /* NOP */
  66. (void)cf;
  67. (void)data;
  68. (void)ps;
  69. return CURLE_OK;
  70. }
  71. bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
  72. const struct Curl_easy *data)
  73. {
  74. return cf->next ?
  75. cf->next->cft->has_data_pending(cf->next, data) : FALSE;
  76. }
  77. CURLcode Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  78. const void *buf, size_t len, bool eos,
  79. size_t *pnwritten)
  80. {
  81. if(cf->next)
  82. return cf->next->cft->do_send(cf->next, data, buf, len, eos, pnwritten);
  83. *pnwritten = 0;
  84. return CURLE_RECV_ERROR;
  85. }
  86. CURLcode Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  87. char *buf, size_t len, size_t *pnread)
  88. {
  89. if(cf->next)
  90. return cf->next->cft->do_recv(cf->next, data, buf, len, pnread);
  91. *pnread = 0;
  92. return CURLE_SEND_ERROR;
  93. }
  94. bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
  95. struct Curl_easy *data,
  96. bool *input_pending)
  97. {
  98. return cf->next ?
  99. cf->next->cft->is_alive(cf->next, data, input_pending) :
  100. FALSE; /* pessimistic in absence of data */
  101. }
  102. CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
  103. struct Curl_easy *data)
  104. {
  105. return cf->next ?
  106. cf->next->cft->keep_alive(cf->next, data) :
  107. CURLE_OK;
  108. }
  109. CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
  110. struct Curl_easy *data,
  111. int query, int *pres1, void *pres2)
  112. {
  113. return cf->next ?
  114. cf->next->cft->query(cf->next, data, query, pres1, pres2) :
  115. CURLE_UNKNOWN_OPTION;
  116. }
  117. void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
  118. struct Curl_easy *data)
  119. {
  120. struct Curl_cfilter *cfn, *cf = *pcf;
  121. if(cf) {
  122. *pcf = NULL;
  123. while(cf) {
  124. cfn = cf->next;
  125. /* prevent destroying filter to mess with its sub-chain, since
  126. * we have the reference now and will call destroy on it.
  127. */
  128. cf->next = NULL;
  129. cf->cft->destroy(cf, data);
  130. free(cf);
  131. cf = cfn;
  132. }
  133. }
  134. }
  135. void Curl_conn_cf_discard_all(struct Curl_easy *data,
  136. struct connectdata *conn, int index)
  137. {
  138. Curl_conn_cf_discard_chain(&conn->cfilter[index], data);
  139. }
  140. void Curl_conn_close(struct Curl_easy *data, int index)
  141. {
  142. struct Curl_cfilter *cf;
  143. DEBUGASSERT(data->conn);
  144. /* it is valid to call that without filters being present */
  145. cf = data->conn->cfilter[index];
  146. if(cf) {
  147. cf->cft->do_close(cf, data);
  148. }
  149. Curl_shutdown_clear(data, index);
  150. }
  151. CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done)
  152. {
  153. struct Curl_cfilter *cf;
  154. CURLcode result = CURLE_OK;
  155. timediff_t timeout_ms;
  156. struct curltime now;
  157. DEBUGASSERT(data->conn);
  158. if(!CONN_SOCK_IDX_VALID(sockindex))
  159. return CURLE_BAD_FUNCTION_ARGUMENT;
  160. /* Get the first connected filter that is not shut down already. */
  161. cf = data->conn->cfilter[sockindex];
  162. while(cf && (!cf->connected || cf->shutdown))
  163. cf = cf->next;
  164. if(!cf) {
  165. *done = TRUE;
  166. return CURLE_OK;
  167. }
  168. *done = FALSE;
  169. now = curlx_now();
  170. if(!Curl_shutdown_started(data, sockindex)) {
  171. CURL_TRC_M(data, "shutdown start on%s connection",
  172. sockindex ? " secondary" : "");
  173. Curl_shutdown_start(data, sockindex, 0, &now);
  174. }
  175. else {
  176. timeout_ms = Curl_shutdown_timeleft(data->conn, sockindex, &now);
  177. if(timeout_ms < 0) {
  178. /* info message, since this might be regarded as acceptable */
  179. infof(data, "shutdown timeout");
  180. return CURLE_OPERATION_TIMEDOUT;
  181. }
  182. }
  183. while(cf) {
  184. if(!cf->shutdown) {
  185. bool cfdone = FALSE;
  186. result = cf->cft->do_shutdown(cf, data, &cfdone);
  187. if(result) {
  188. CURL_TRC_CF(data, cf, "shut down failed with %d", result);
  189. return result;
  190. }
  191. else if(!cfdone) {
  192. CURL_TRC_CF(data, cf, "shut down not done yet");
  193. return CURLE_OK;
  194. }
  195. CURL_TRC_CF(data, cf, "shut down successfully");
  196. cf->shutdown = TRUE;
  197. }
  198. cf = cf->next;
  199. }
  200. *done = (!result);
  201. return result;
  202. }
  203. CURLcode Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
  204. size_t len, size_t *pnread)
  205. {
  206. struct Curl_cfilter *cf;
  207. DEBUGASSERT(data);
  208. DEBUGASSERT(data->conn);
  209. cf = data->conn->cfilter[num];
  210. while(cf && !cf->connected)
  211. cf = cf->next;
  212. if(cf)
  213. return cf->cft->do_recv(cf, data, buf, len, pnread);
  214. failf(data, "recv: no filter connected");
  215. DEBUGASSERT(0);
  216. *pnread = 0;
  217. return CURLE_FAILED_INIT;
  218. }
  219. CURLcode Curl_cf_send(struct Curl_easy *data, int num,
  220. const void *mem, size_t len, bool eos,
  221. size_t *pnwritten)
  222. {
  223. struct Curl_cfilter *cf;
  224. DEBUGASSERT(data);
  225. DEBUGASSERT(data->conn);
  226. cf = data->conn->cfilter[num];
  227. while(cf && !cf->connected)
  228. cf = cf->next;
  229. if(cf) {
  230. return cf->cft->do_send(cf, data, mem, len, eos, pnwritten);
  231. }
  232. failf(data, "send: no filter connected");
  233. DEBUGASSERT(0);
  234. *pnwritten = 0;
  235. return CURLE_FAILED_INIT;
  236. }
  237. struct cf_io_ctx {
  238. struct Curl_easy *data;
  239. struct Curl_cfilter *cf;
  240. };
  241. static CURLcode cf_bufq_reader(void *writer_ctx,
  242. unsigned char *buf, size_t blen,
  243. size_t *pnread)
  244. {
  245. struct cf_io_ctx *io = writer_ctx;
  246. return Curl_conn_cf_recv(io->cf, io->data, (char *)buf, blen, pnread);
  247. }
  248. CURLcode Curl_cf_recv_bufq(struct Curl_cfilter *cf,
  249. struct Curl_easy *data,
  250. struct bufq *bufq,
  251. size_t maxlen,
  252. size_t *pnread)
  253. {
  254. struct cf_io_ctx io;
  255. if(!cf || !data) {
  256. *pnread = 0;
  257. return CURLE_BAD_FUNCTION_ARGUMENT;
  258. }
  259. io.data = data;
  260. io.cf = cf;
  261. return Curl_bufq_sipn(bufq, maxlen, cf_bufq_reader, &io, pnread);
  262. }
  263. static CURLcode cf_bufq_writer(void *writer_ctx,
  264. const unsigned char *buf, size_t buflen,
  265. size_t *pnwritten)
  266. {
  267. struct cf_io_ctx *io = writer_ctx;
  268. return Curl_conn_cf_send(io->cf, io->data, (const char *)buf,
  269. buflen, FALSE, pnwritten);
  270. }
  271. CURLcode Curl_cf_send_bufq(struct Curl_cfilter *cf,
  272. struct Curl_easy *data,
  273. struct bufq *bufq,
  274. const unsigned char *buf, size_t blen,
  275. size_t *pnwritten)
  276. {
  277. struct cf_io_ctx io;
  278. if(!cf || !data) {
  279. *pnwritten = 0;
  280. return CURLE_BAD_FUNCTION_ARGUMENT;
  281. }
  282. io.data = data;
  283. io.cf = cf;
  284. if(buf && blen)
  285. return Curl_bufq_write_pass(bufq, buf, blen, cf_bufq_writer, &io,
  286. pnwritten);
  287. else
  288. return Curl_bufq_pass(bufq, cf_bufq_writer, &io, pnwritten);
  289. }
  290. CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
  291. const struct Curl_cftype *cft,
  292. void *ctx)
  293. {
  294. struct Curl_cfilter *cf;
  295. CURLcode result = CURLE_OUT_OF_MEMORY;
  296. DEBUGASSERT(cft);
  297. cf = calloc(1, sizeof(*cf));
  298. if(!cf)
  299. goto out;
  300. cf->cft = cft;
  301. cf->ctx = ctx;
  302. result = CURLE_OK;
  303. out:
  304. *pcf = cf;
  305. return result;
  306. }
  307. void Curl_conn_cf_add(struct Curl_easy *data,
  308. struct connectdata *conn,
  309. int index,
  310. struct Curl_cfilter *cf)
  311. {
  312. (void)data;
  313. DEBUGASSERT(conn);
  314. DEBUGASSERT(!cf->conn);
  315. DEBUGASSERT(!cf->next);
  316. cf->next = conn->cfilter[index];
  317. cf->conn = conn;
  318. cf->sockindex = index;
  319. conn->cfilter[index] = cf;
  320. CURL_TRC_CF(data, cf, "added");
  321. }
  322. void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
  323. struct Curl_cfilter *cf_new)
  324. {
  325. struct Curl_cfilter *tail, **pnext;
  326. DEBUGASSERT(cf_at);
  327. DEBUGASSERT(cf_new);
  328. DEBUGASSERT(!cf_new->conn);
  329. tail = cf_at->next;
  330. cf_at->next = cf_new;
  331. do {
  332. cf_new->conn = cf_at->conn;
  333. cf_new->sockindex = cf_at->sockindex;
  334. pnext = &cf_new->next;
  335. cf_new = cf_new->next;
  336. } while(cf_new);
  337. *pnext = tail;
  338. }
  339. bool Curl_conn_cf_discard(struct Curl_cfilter **pcf,
  340. struct Curl_easy *data)
  341. {
  342. struct Curl_cfilter *cf = pcf ? *pcf : NULL;
  343. bool found = FALSE;
  344. if(cf) {
  345. if(cf->conn) {
  346. /* unlink if present in connection filter chain */
  347. struct Curl_cfilter **pprev = &cf->conn->cfilter[cf->sockindex];
  348. while(*pprev) {
  349. if(*pprev == *pcf) {
  350. *pprev = (*pcf)->next;
  351. cf->next = NULL;
  352. found = TRUE;
  353. break;
  354. }
  355. pprev = &((*pprev)->next);
  356. }
  357. }
  358. Curl_conn_cf_discard_chain(pcf, data);
  359. }
  360. return found;
  361. }
  362. CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
  363. struct Curl_easy *data,
  364. bool *done)
  365. {
  366. if(cf)
  367. return cf->cft->do_connect(cf, data, done);
  368. return CURLE_FAILED_INIT;
  369. }
  370. void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  371. {
  372. if(cf)
  373. cf->cft->do_close(cf, data);
  374. }
  375. CURLcode Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  376. const void *buf, size_t len, bool eos,
  377. size_t *pnwritten)
  378. {
  379. if(cf)
  380. return cf->cft->do_send(cf, data, buf, len, eos, pnwritten);
  381. *pnwritten = 0;
  382. return CURLE_SEND_ERROR;
  383. }
  384. CURLcode Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  385. char *buf, size_t len, size_t *pnread)
  386. {
  387. if(cf)
  388. return cf->cft->do_recv(cf, data, buf, len, pnread);
  389. *pnread = 0;
  390. return CURLE_RECV_ERROR;
  391. }
  392. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  393. static CURLcode cf_verboseconnect(struct Curl_easy *data,
  394. struct Curl_cfilter *cf)
  395. {
  396. if(Curl_trc_is_verbose(data)) {
  397. struct ip_quadruple ipquad;
  398. bool is_ipv6;
  399. CURLcode result;
  400. result = Curl_conn_cf_get_ip_info(cf, data, &is_ipv6, &ipquad);
  401. if(result)
  402. return result;
  403. infof(data, "Established %sconnection to %s (%s port %u) from %s port %u ",
  404. (cf->sockindex == SECONDARYSOCKET) ? "2nd " : "",
  405. CURL_CONN_HOST_DISPNAME(data->conn),
  406. ipquad.remote_ip, ipquad.remote_port,
  407. ipquad.local_ip, ipquad.local_port);
  408. }
  409. return CURLE_OK;
  410. }
  411. #endif
  412. CURLcode Curl_conn_connect(struct Curl_easy *data,
  413. int sockindex,
  414. bool blocking,
  415. bool *done)
  416. {
  417. #define CF_CONN_NUM_POLLS_ON_STACK 5
  418. struct pollfd a_few_on_stack[CF_CONN_NUM_POLLS_ON_STACK];
  419. struct easy_pollset ps;
  420. struct curl_pollfds cpfds;
  421. struct Curl_cfilter *cf;
  422. CURLcode result = CURLE_OK;
  423. DEBUGASSERT(data);
  424. DEBUGASSERT(data->conn);
  425. if(!CONN_SOCK_IDX_VALID(sockindex))
  426. return CURLE_BAD_FUNCTION_ARGUMENT;
  427. cf = data->conn->cfilter[sockindex];
  428. if(!cf) {
  429. *done = FALSE;
  430. return CURLE_FAILED_INIT;
  431. }
  432. *done = cf->connected;
  433. if(*done)
  434. return CURLE_OK;
  435. Curl_pollset_init(&ps);
  436. Curl_pollfds_init(&cpfds, a_few_on_stack, CF_CONN_NUM_POLLS_ON_STACK);
  437. while(!*done) {
  438. if(Curl_conn_needs_flush(data, sockindex)) {
  439. DEBUGF(infof(data, "Curl_conn_connect(index=%d), flush", sockindex));
  440. result = Curl_conn_flush(data, sockindex);
  441. if(result && (result != CURLE_AGAIN))
  442. return result;
  443. }
  444. result = cf->cft->do_connect(cf, data, done);
  445. CURL_TRC_CF(data, cf, "Curl_conn_connect(block=%d) -> %d, done=%d",
  446. blocking, result, *done);
  447. if(!result && *done) {
  448. /* Now that the complete filter chain is connected, let all filters
  449. * persist information at the connection. E.g. cf-socket sets the
  450. * socket and ip related information. */
  451. cf_cntrl_update_info(data, data->conn);
  452. conn_report_connect_stats(data, data->conn);
  453. data->conn->keepalive = curlx_now();
  454. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  455. result = cf_verboseconnect(data, cf);
  456. #endif
  457. goto out;
  458. }
  459. else if(result) {
  460. CURL_TRC_CF(data, cf, "Curl_conn_connect(), filter returned %d",
  461. result);
  462. conn_report_connect_stats(data, data->conn);
  463. goto out;
  464. }
  465. if(!blocking)
  466. goto out;
  467. else {
  468. /* check allowed time left */
  469. const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
  470. curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
  471. int rc;
  472. if(timeout_ms < 0) {
  473. /* no need to continue if time already is up */
  474. failf(data, "connect timeout");
  475. result = CURLE_OPERATION_TIMEDOUT;
  476. goto out;
  477. }
  478. CURL_TRC_CF(data, cf, "Curl_conn_connect(block=1), do poll");
  479. Curl_pollset_reset(&ps);
  480. Curl_pollfds_reset(&cpfds);
  481. /* In general, we want to send after connect, wait on that. */
  482. if(sockfd != CURL_SOCKET_BAD)
  483. result = Curl_pollset_set_out_only(data, &ps, sockfd);
  484. if(!result)
  485. result = Curl_conn_adjust_pollset(data, data->conn, &ps);
  486. if(result)
  487. goto out;
  488. result = Curl_pollfds_add_ps(&cpfds, &ps);
  489. if(result)
  490. goto out;
  491. rc = Curl_poll(cpfds.pfds, cpfds.n,
  492. CURLMIN(timeout_ms, (cpfds.n ? 1000 : 10)));
  493. CURL_TRC_CF(data, cf, "Curl_conn_connect(block=1), Curl_poll() -> %d",
  494. rc);
  495. if(rc < 0) {
  496. result = CURLE_COULDNT_CONNECT;
  497. goto out;
  498. }
  499. /* continue iterating */
  500. }
  501. }
  502. out:
  503. Curl_pollset_cleanup(&ps);
  504. Curl_pollfds_cleanup(&cpfds);
  505. return result;
  506. }
  507. bool Curl_conn_is_setup(struct connectdata *conn, int sockindex)
  508. {
  509. if(!CONN_SOCK_IDX_VALID(sockindex))
  510. return FALSE;
  511. return (conn->cfilter[sockindex] != NULL);
  512. }
  513. bool Curl_conn_is_connected(struct connectdata *conn, int sockindex)
  514. {
  515. struct Curl_cfilter *cf;
  516. if(!CONN_SOCK_IDX_VALID(sockindex))
  517. return FALSE;
  518. cf = conn->cfilter[sockindex];
  519. return cf && cf->connected;
  520. }
  521. bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex)
  522. {
  523. struct Curl_cfilter *cf;
  524. if(!CONN_SOCK_IDX_VALID(sockindex))
  525. return FALSE;
  526. cf = data->conn->cfilter[sockindex];
  527. while(cf) {
  528. if(cf->connected)
  529. return TRUE;
  530. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  531. return FALSE;
  532. cf = cf->next;
  533. }
  534. return FALSE;
  535. }
  536. static bool cf_is_ssl(struct Curl_cfilter *cf)
  537. {
  538. for(; cf; cf = cf->next) {
  539. if(cf->cft->flags & CF_TYPE_SSL)
  540. return TRUE;
  541. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  542. return FALSE;
  543. }
  544. return FALSE;
  545. }
  546. bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex)
  547. {
  548. if(!CONN_SOCK_IDX_VALID(sockindex))
  549. return FALSE;
  550. return conn ? cf_is_ssl(conn->cfilter[sockindex]) : FALSE;
  551. }
  552. bool Curl_conn_get_ssl_info(struct Curl_easy *data,
  553. struct connectdata *conn, int sockindex,
  554. struct curl_tlssessioninfo *info)
  555. {
  556. if(!CONN_SOCK_IDX_VALID(sockindex))
  557. return FALSE;
  558. if(Curl_conn_is_ssl(conn, sockindex)) {
  559. struct Curl_cfilter *cf = conn->cfilter[sockindex];
  560. CURLcode result = cf ? cf->cft->query(cf, data, CF_QUERY_SSL_INFO,
  561. NULL, (void *)info) : CURLE_UNKNOWN_OPTION;
  562. return !result;
  563. }
  564. return FALSE;
  565. }
  566. CURLcode Curl_conn_get_ip_info(struct Curl_easy *data,
  567. struct connectdata *conn, int sockindex,
  568. bool *is_ipv6, struct ip_quadruple *ipquad)
  569. {
  570. struct Curl_cfilter *cf;
  571. if(!CONN_SOCK_IDX_VALID(sockindex))
  572. return CURLE_BAD_FUNCTION_ARGUMENT;
  573. cf = conn ? conn->cfilter[sockindex] : NULL;
  574. return Curl_conn_cf_get_ip_info(cf, data, is_ipv6, ipquad);
  575. }
  576. bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex)
  577. {
  578. struct Curl_cfilter *cf;
  579. if(!CONN_SOCK_IDX_VALID(sockindex))
  580. return FALSE;
  581. cf = conn ? conn->cfilter[sockindex] : NULL;
  582. for(; cf; cf = cf->next) {
  583. if(cf->cft->flags & CF_TYPE_MULTIPLEX)
  584. return TRUE;
  585. if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL))
  586. return FALSE;
  587. }
  588. return FALSE;
  589. }
  590. unsigned char Curl_conn_get_transport(struct Curl_easy *data,
  591. struct connectdata *conn)
  592. {
  593. struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
  594. return Curl_conn_cf_get_transport(cf, data);
  595. }
  596. const char *Curl_conn_get_alpn_negotiated(struct Curl_easy *data,
  597. struct connectdata *conn)
  598. {
  599. struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
  600. return Curl_conn_cf_get_alpn_negotiated(cf, data);
  601. }
  602. unsigned char Curl_conn_http_version(struct Curl_easy *data,
  603. struct connectdata *conn)
  604. {
  605. struct Curl_cfilter *cf;
  606. CURLcode result = CURLE_UNKNOWN_OPTION;
  607. unsigned char v = 0;
  608. cf = conn->cfilter[FIRSTSOCKET];
  609. for(; cf; cf = cf->next) {
  610. if(cf->cft->flags & CF_TYPE_HTTP) {
  611. int value = 0;
  612. result = cf->cft->query(cf, data, CF_QUERY_HTTP_VERSION, &value, NULL);
  613. if(!result && ((value < 0) || (value > 255)))
  614. result = CURLE_FAILED_INIT;
  615. else
  616. v = (unsigned char)value;
  617. break;
  618. }
  619. if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL))
  620. break;
  621. }
  622. return (unsigned char)(result ? 0 : v);
  623. }
  624. bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
  625. {
  626. struct Curl_cfilter *cf;
  627. (void)data;
  628. DEBUGASSERT(data);
  629. DEBUGASSERT(data->conn);
  630. if(!CONN_SOCK_IDX_VALID(sockindex))
  631. return FALSE;
  632. cf = data->conn->cfilter[sockindex];
  633. while(cf && !cf->connected) {
  634. cf = cf->next;
  635. }
  636. if(cf) {
  637. return cf->cft->has_data_pending(cf, data);
  638. }
  639. return FALSE;
  640. }
  641. bool Curl_conn_cf_needs_flush(struct Curl_cfilter *cf,
  642. struct Curl_easy *data)
  643. {
  644. CURLcode result;
  645. int pending = 0;
  646. result = cf ? cf->cft->query(cf, data, CF_QUERY_NEED_FLUSH,
  647. &pending, NULL) : CURLE_UNKNOWN_OPTION;
  648. return (result || !pending) ? FALSE : TRUE;
  649. }
  650. bool Curl_conn_needs_flush(struct Curl_easy *data, int sockindex)
  651. {
  652. if(!CONN_SOCK_IDX_VALID(sockindex))
  653. return FALSE;
  654. return Curl_conn_cf_needs_flush(data->conn->cfilter[sockindex], data);
  655. }
  656. CURLcode Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
  657. struct Curl_easy *data,
  658. struct easy_pollset *ps)
  659. {
  660. CURLcode result = CURLE_OK;
  661. /* Get the lowest not-connected filter, if there are any */
  662. while(cf && !cf->connected && cf->next && !cf->next->connected)
  663. cf = cf->next;
  664. /* Skip all filters that have already shut down */
  665. while(cf && cf->shutdown)
  666. cf = cf->next;
  667. /* From there on, give all filters a chance to adjust the pollset.
  668. * Lower filters are called later, so they may override */
  669. while(cf && !result) {
  670. result = cf->cft->adjust_pollset(cf, data, ps);
  671. cf = cf->next;
  672. }
  673. return result;
  674. }
  675. CURLcode Curl_conn_adjust_pollset(struct Curl_easy *data,
  676. struct connectdata *conn,
  677. struct easy_pollset *ps)
  678. {
  679. CURLcode result = CURLE_OK;
  680. int i;
  681. DEBUGASSERT(data);
  682. DEBUGASSERT(conn);
  683. for(i = 0; (i < 2) && !result; ++i) {
  684. result = Curl_conn_cf_adjust_pollset(conn->cfilter[i], data, ps);
  685. }
  686. return result;
  687. }
  688. int Curl_conn_cf_poll(struct Curl_cfilter *cf,
  689. struct Curl_easy *data,
  690. timediff_t timeout_ms)
  691. {
  692. struct easy_pollset ps;
  693. int result;
  694. DEBUGASSERT(cf);
  695. DEBUGASSERT(data);
  696. DEBUGASSERT(data->conn);
  697. Curl_pollset_init(&ps);
  698. result = Curl_conn_cf_adjust_pollset(cf, data, &ps);
  699. if(!result)
  700. result = Curl_pollset_poll(data, &ps, timeout_ms);
  701. Curl_pollset_cleanup(&ps);
  702. return result;
  703. }
  704. void Curl_conn_get_current_host(struct Curl_easy *data, int sockindex,
  705. const char **phost, int *pport)
  706. {
  707. struct Curl_cfilter *cf, *cf_proxy = NULL;
  708. if(!data->conn) {
  709. DEBUGASSERT(0);
  710. *phost = "";
  711. *pport = -1;
  712. return;
  713. }
  714. cf = CONN_SOCK_IDX_VALID(sockindex) ? data->conn->cfilter[sockindex] : NULL;
  715. /* Find the "lowest" tunneling proxy filter that has not connected yet. */
  716. while(cf && !cf->connected) {
  717. if((cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_PROXY)) ==
  718. (CF_TYPE_IP_CONNECT|CF_TYPE_PROXY))
  719. cf_proxy = cf;
  720. cf = cf->next;
  721. }
  722. /* cf_proxy (!= NULL) is not connected yet. It is talking
  723. * to an interim host and any authentication or other things apply
  724. * to this interim host and port. */
  725. if(!cf_proxy || cf_proxy->cft->query(cf_proxy, data, CF_QUERY_HOST_PORT,
  726. pport, CURL_UNCONST(phost))) {
  727. /* Everything connected or query unsuccessful, the overall
  728. * connection's destination is the answer */
  729. *phost = data->conn->host.name;
  730. *pport = data->conn->remote_port;
  731. }
  732. }
  733. CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
  734. struct Curl_easy *data,
  735. int event, int arg1, void *arg2)
  736. {
  737. (void)cf;
  738. (void)data;
  739. (void)event;
  740. (void)arg1;
  741. (void)arg2;
  742. return CURLE_OK;
  743. }
  744. CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
  745. struct Curl_easy *data,
  746. bool ignore_result,
  747. int event, int arg1, void *arg2)
  748. {
  749. CURLcode result = CURLE_OK;
  750. for(; cf; cf = cf->next) {
  751. if(Curl_cf_def_cntrl == cf->cft->cntrl)
  752. continue;
  753. result = cf->cft->cntrl(cf, data, event, arg1, arg2);
  754. if(!ignore_result && result)
  755. break;
  756. }
  757. return result;
  758. }
  759. curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
  760. struct Curl_easy *data)
  761. {
  762. curl_socket_t sock;
  763. if(cf && !cf->cft->query(cf, data, CF_QUERY_SOCKET, NULL, &sock))
  764. return sock;
  765. return CURL_SOCKET_BAD;
  766. }
  767. unsigned char Curl_conn_cf_get_transport(struct Curl_cfilter *cf,
  768. struct Curl_easy *data)
  769. {
  770. int transport = 0;
  771. if(cf && !cf->cft->query(cf, data, CF_QUERY_TRANSPORT, &transport, NULL))
  772. return (unsigned char)transport;
  773. return (unsigned char)(data->conn ? data->conn->transport_wanted : 0);
  774. }
  775. const char *Curl_conn_cf_get_alpn_negotiated(struct Curl_cfilter *cf,
  776. struct Curl_easy *data)
  777. {
  778. const char *alpn = NULL;
  779. CURL_TRC_CF(data, cf, "query ALPN");
  780. if(cf && !cf->cft->query(cf, data, CF_QUERY_ALPN_NEGOTIATED, NULL,
  781. CURL_UNCONST(&alpn)))
  782. return alpn;
  783. return NULL;
  784. }
  785. static const struct Curl_sockaddr_ex *
  786. cf_get_remote_addr(struct Curl_cfilter *cf, struct Curl_easy *data)
  787. {
  788. const struct Curl_sockaddr_ex *remote_addr = NULL;
  789. if(cf &&
  790. !cf->cft->query(cf, data, CF_QUERY_REMOTE_ADDR, NULL,
  791. CURL_UNCONST(&remote_addr)))
  792. return remote_addr;
  793. return NULL;
  794. }
  795. CURLcode Curl_conn_cf_get_ip_info(struct Curl_cfilter *cf,
  796. struct Curl_easy *data,
  797. bool *is_ipv6, struct ip_quadruple *ipquad)
  798. {
  799. CURLcode result = CURLE_UNKNOWN_OPTION;
  800. if(cf) {
  801. int ipv6 = 0;
  802. result = cf->cft->query(cf, data, CF_QUERY_IP_INFO, &ipv6, ipquad);
  803. *is_ipv6 = !!ipv6;
  804. }
  805. return result;
  806. }
  807. curl_socket_t Curl_conn_get_first_socket(struct Curl_easy *data)
  808. {
  809. struct Curl_cfilter *cf;
  810. if(!data->conn)
  811. return CURL_SOCKET_BAD;
  812. cf = data->conn->cfilter[FIRSTSOCKET];
  813. /* if the top filter has not connected, ask it (and its sub-filters)
  814. * for the socket. Otherwise conn->sock[sockindex] should have it. */
  815. if(cf && !cf->connected)
  816. return Curl_conn_cf_get_socket(cf, data);
  817. return data->conn->sock[FIRSTSOCKET];
  818. }
  819. const struct Curl_sockaddr_ex *
  820. Curl_conn_get_remote_addr(struct Curl_easy *data, int sockindex)
  821. {
  822. struct Curl_cfilter *cf =
  823. (data->conn && CONN_SOCK_IDX_VALID(sockindex)) ?
  824. data->conn->cfilter[sockindex] : NULL;
  825. return cf ? cf_get_remote_addr(cf, data) : NULL;
  826. }
  827. void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
  828. {
  829. struct connectdata *conn = data->conn;
  830. if(conn && CONN_SOCK_IDX_VALID(sockindex)) {
  831. struct Curl_cfilter *cf = conn->cfilter[sockindex];
  832. if(cf)
  833. (void)Curl_conn_cf_cntrl(cf, data, TRUE,
  834. CF_CTRL_FORGET_SOCKET, 0, NULL);
  835. fake_sclose(conn->sock[sockindex]);
  836. conn->sock[sockindex] = CURL_SOCKET_BAD;
  837. }
  838. }
  839. static CURLcode cf_cntrl_all(struct connectdata *conn,
  840. struct Curl_easy *data,
  841. bool ignore_result,
  842. int event, int arg1, void *arg2)
  843. {
  844. CURLcode result = CURLE_OK;
  845. size_t i;
  846. for(i = 0; i < CURL_ARRAYSIZE(conn->cfilter); ++i) {
  847. result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
  848. event, arg1, arg2);
  849. if(!ignore_result && result)
  850. break;
  851. }
  852. return result;
  853. }
  854. CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
  855. {
  856. return cf_cntrl_all(data->conn, data, FALSE,
  857. CF_CTRL_DATA_SETUP, 0, NULL);
  858. }
  859. CURLcode Curl_conn_flush(struct Curl_easy *data, int sockindex)
  860. {
  861. if(!CONN_SOCK_IDX_VALID(sockindex))
  862. return CURLE_BAD_FUNCTION_ARGUMENT;
  863. return Curl_conn_cf_cntrl(data->conn->cfilter[sockindex], data, FALSE,
  864. CF_CTRL_FLUSH, 0, NULL);
  865. }
  866. /**
  867. * Notify connection filters that the transfer represented by `data`
  868. * is done with sending data (e.g. has uploaded everything).
  869. */
  870. void Curl_conn_ev_data_done_send(struct Curl_easy *data)
  871. {
  872. cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE_SEND, 0, NULL);
  873. }
  874. /**
  875. * Notify connection filters that the transfer represented by `data`
  876. * is finished - eventually premature, e.g. before being complete.
  877. */
  878. void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature)
  879. {
  880. cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE, premature, NULL);
  881. }
  882. CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause)
  883. {
  884. return cf_cntrl_all(data->conn, data, FALSE,
  885. CF_CTRL_DATA_PAUSE, do_pause, NULL);
  886. }
  887. static void cf_cntrl_update_info(struct Curl_easy *data,
  888. struct connectdata *conn)
  889. {
  890. cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
  891. }
  892. /**
  893. * Update connection statistics
  894. */
  895. static void conn_report_connect_stats(struct Curl_easy *data,
  896. struct connectdata *conn)
  897. {
  898. struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
  899. if(cf) {
  900. struct curltime connected;
  901. struct curltime appconnected;
  902. memset(&connected, 0, sizeof(connected));
  903. cf->cft->query(cf, data, CF_QUERY_TIMER_CONNECT, NULL, &connected);
  904. if(connected.tv_sec || connected.tv_usec)
  905. Curl_pgrsTimeWas(data, TIMER_CONNECT, connected);
  906. memset(&appconnected, 0, sizeof(appconnected));
  907. cf->cft->query(cf, data, CF_QUERY_TIMER_APPCONNECT, NULL, &appconnected);
  908. if(appconnected.tv_sec || appconnected.tv_usec)
  909. Curl_pgrsTimeWas(data, TIMER_APPCONNECT, appconnected);
  910. }
  911. }
  912. bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
  913. bool *input_pending)
  914. {
  915. struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
  916. return cf && !cf->conn->bits.close &&
  917. cf->cft->is_alive(cf, data, input_pending);
  918. }
  919. CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
  920. struct connectdata *conn,
  921. int sockindex)
  922. {
  923. struct Curl_cfilter *cf;
  924. if(!CONN_SOCK_IDX_VALID(sockindex))
  925. return CURLE_BAD_FUNCTION_ARGUMENT;
  926. cf = conn->cfilter[sockindex];
  927. return cf ? cf->cft->keep_alive(cf, data) : CURLE_OK;
  928. }
  929. size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
  930. struct connectdata *conn,
  931. int sockindex)
  932. {
  933. struct Curl_cfilter *cf;
  934. CURLcode result;
  935. int n = -1;
  936. if(!CONN_SOCK_IDX_VALID(sockindex))
  937. return 0;
  938. cf = conn->cfilter[sockindex];
  939. result = cf ? cf->cft->query(cf, data, CF_QUERY_MAX_CONCURRENT,
  940. &n, NULL) : CURLE_UNKNOWN_OPTION;
  941. /* If no filter answered the query, the default is a non-multiplexed
  942. * connection with limit 1. Otherwise, the the query may return 0
  943. * for connections that are in shutdown, e.g. server HTTP/2 GOAWAY. */
  944. return (result || n < 0) ? 1 : (size_t)n;
  945. }
  946. int Curl_conn_get_stream_error(struct Curl_easy *data,
  947. struct connectdata *conn,
  948. int sockindex)
  949. {
  950. struct Curl_cfilter *cf;
  951. CURLcode result;
  952. int n = 0;
  953. if(!CONN_SOCK_IDX_VALID(sockindex))
  954. return 0;
  955. cf = conn->cfilter[sockindex];
  956. result = cf ? cf->cft->query(cf, data, CF_QUERY_STREAM_ERROR,
  957. &n, NULL) : CURLE_UNKNOWN_OPTION;
  958. return (result || n < 0) ? 0 : n;
  959. }
  960. int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd)
  961. {
  962. if(data && data->conn &&
  963. sockfd != CURL_SOCKET_BAD && sockfd == data->conn->sock[SECONDARYSOCKET])
  964. return SECONDARYSOCKET;
  965. return FIRSTSOCKET;
  966. }
  967. CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
  968. char *buf, size_t blen, size_t *pnread)
  969. {
  970. DEBUGASSERT(data);
  971. DEBUGASSERT(data->conn);
  972. if(!CONN_SOCK_IDX_VALID(sockindex))
  973. return CURLE_BAD_FUNCTION_ARGUMENT;
  974. if(data && data->conn && data->conn->recv[sockindex])
  975. return data->conn->recv[sockindex](data, sockindex, buf, blen, pnread);
  976. *pnread = 0;
  977. return CURLE_FAILED_INIT;
  978. }
  979. CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
  980. const void *buf, size_t blen, bool eos,
  981. size_t *pnwritten)
  982. {
  983. size_t write_len = blen;
  984. DEBUGASSERT(data);
  985. DEBUGASSERT(data->conn);
  986. DEBUGASSERT(CONN_SOCK_IDX_VALID(sockindex));
  987. if(!CONN_SOCK_IDX_VALID(sockindex))
  988. return CURLE_BAD_FUNCTION_ARGUMENT;
  989. #ifdef DEBUGBUILD
  990. if(write_len) {
  991. /* Allow debug builds to override this logic to force short sends
  992. */
  993. const char *p = getenv("CURL_SMALLSENDS");
  994. if(p) {
  995. curl_off_t altsize;
  996. if(!curlx_str_number(&p, &altsize, write_len))
  997. write_len = (size_t)altsize;
  998. }
  999. }
  1000. #endif
  1001. if(write_len != blen)
  1002. eos = FALSE;
  1003. if(data && data->conn && data->conn->send[sockindex])
  1004. return data->conn->send[sockindex](data, sockindex, buf, write_len, eos,
  1005. pnwritten);
  1006. *pnwritten = 0;
  1007. return CURLE_FAILED_INIT;
  1008. }