cfilters.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  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.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" /* for Curl_safefree() */
  30. #include "sendf.h"
  31. #include "sockaddr.h" /* required for Curl_sockaddr_storage */
  32. #include "multiif.h"
  33. #include "progress.h"
  34. #include "warnless.h"
  35. /* The last 3 #include files should be in this order */
  36. #include "curl_printf.h"
  37. #include "curl_memory.h"
  38. #include "memdebug.h"
  39. #ifndef ARRAYSIZE
  40. #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
  41. #endif
  42. #ifdef DEBUGBUILD
  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. static void conn_report_connect_stats(struct Curl_easy *data,
  52. struct connectdata *conn);
  53. void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
  54. const char **phost, const char **pdisplay_host,
  55. int *pport)
  56. {
  57. if(cf->next)
  58. cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
  59. else {
  60. *phost = cf->conn->host.name;
  61. *pdisplay_host = cf->conn->host.dispname;
  62. *pport = cf->conn->port;
  63. }
  64. }
  65. int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
  66. struct Curl_easy *data,
  67. curl_socket_t *socks)
  68. {
  69. return cf->next?
  70. cf->next->cft->get_select_socks(cf->next, data, socks) : 0;
  71. }
  72. bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
  73. const struct Curl_easy *data)
  74. {
  75. return cf->next?
  76. cf->next->cft->has_data_pending(cf->next, data) : FALSE;
  77. }
  78. ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  79. const void *buf, size_t len, CURLcode *err)
  80. {
  81. return cf->next?
  82. cf->next->cft->do_send(cf->next, data, buf, len, err) :
  83. CURLE_RECV_ERROR;
  84. }
  85. ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  86. char *buf, size_t len, CURLcode *err)
  87. {
  88. return cf->next?
  89. cf->next->cft->do_recv(cf->next, data, buf, len, err) :
  90. CURLE_SEND_ERROR;
  91. }
  92. bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
  93. struct Curl_easy *data,
  94. bool *input_pending)
  95. {
  96. return cf->next?
  97. cf->next->cft->is_alive(cf->next, data, input_pending) :
  98. FALSE; /* pessimistic in absence of data */
  99. }
  100. CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
  101. struct Curl_easy *data)
  102. {
  103. return cf->next?
  104. cf->next->cft->keep_alive(cf->next, data) :
  105. CURLE_OK;
  106. }
  107. CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
  108. struct Curl_easy *data,
  109. int query, int *pres1, void *pres2)
  110. {
  111. return cf->next?
  112. cf->next->cft->query(cf->next, data, query, pres1, pres2) :
  113. CURLE_UNKNOWN_OPTION;
  114. }
  115. void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
  116. struct Curl_easy *data)
  117. {
  118. struct Curl_cfilter *cfn, *cf = *pcf;
  119. if(cf) {
  120. *pcf = NULL;
  121. while(cf) {
  122. cfn = cf->next;
  123. /* prevent destroying filter to mess with its sub-chain, since
  124. * we have the reference now and will call destroy on it.
  125. */
  126. cf->next = NULL;
  127. cf->cft->destroy(cf, data);
  128. free(cf);
  129. cf = cfn;
  130. }
  131. }
  132. }
  133. void Curl_conn_cf_discard_all(struct Curl_easy *data,
  134. struct connectdata *conn, int index)
  135. {
  136. Curl_conn_cf_discard_chain(&conn->cfilter[index], data);
  137. }
  138. void Curl_conn_close(struct Curl_easy *data, int index)
  139. {
  140. struct Curl_cfilter *cf;
  141. DEBUGASSERT(data->conn);
  142. /* it is valid to call that without filters being present */
  143. cf = data->conn->cfilter[index];
  144. if(cf) {
  145. cf->cft->do_close(cf, data);
  146. }
  147. }
  148. ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
  149. size_t len, CURLcode *code)
  150. {
  151. struct Curl_cfilter *cf;
  152. DEBUGASSERT(data);
  153. DEBUGASSERT(data->conn);
  154. cf = data->conn->cfilter[num];
  155. while(cf && !cf->connected) {
  156. cf = cf->next;
  157. }
  158. if(cf) {
  159. return cf->cft->do_recv(cf, data, buf, len, code);
  160. }
  161. failf(data, "recv: no filter connected");
  162. *code = CURLE_FAILED_INIT;
  163. return -1;
  164. }
  165. ssize_t Curl_conn_send(struct Curl_easy *data, int num,
  166. const void *mem, size_t len, CURLcode *code)
  167. {
  168. struct Curl_cfilter *cf;
  169. DEBUGASSERT(data);
  170. DEBUGASSERT(data->conn);
  171. cf = data->conn->cfilter[num];
  172. while(cf && !cf->connected) {
  173. cf = cf->next;
  174. }
  175. if(cf) {
  176. return cf->cft->do_send(cf, data, mem, len, code);
  177. }
  178. failf(data, "send: no filter connected");
  179. DEBUGASSERT(0);
  180. *code = CURLE_FAILED_INIT;
  181. return -1;
  182. }
  183. CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
  184. const struct Curl_cftype *cft,
  185. void *ctx)
  186. {
  187. struct Curl_cfilter *cf;
  188. CURLcode result = CURLE_OUT_OF_MEMORY;
  189. DEBUGASSERT(cft);
  190. cf = calloc(sizeof(*cf), 1);
  191. if(!cf)
  192. goto out;
  193. cf->cft = cft;
  194. cf->ctx = ctx;
  195. result = CURLE_OK;
  196. out:
  197. *pcf = cf;
  198. return result;
  199. }
  200. void Curl_conn_cf_add(struct Curl_easy *data,
  201. struct connectdata *conn,
  202. int index,
  203. struct Curl_cfilter *cf)
  204. {
  205. (void)data;
  206. DEBUGASSERT(conn);
  207. DEBUGASSERT(!cf->conn);
  208. DEBUGASSERT(!cf->next);
  209. cf->next = conn->cfilter[index];
  210. cf->conn = conn;
  211. cf->sockindex = index;
  212. conn->cfilter[index] = cf;
  213. CURL_TRC_CF(data, cf, "added");
  214. }
  215. void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
  216. struct Curl_cfilter *cf_new)
  217. {
  218. struct Curl_cfilter *tail, **pnext;
  219. DEBUGASSERT(cf_at);
  220. DEBUGASSERT(cf_new);
  221. DEBUGASSERT(!cf_new->conn);
  222. tail = cf_at->next;
  223. cf_at->next = cf_new;
  224. do {
  225. cf_new->conn = cf_at->conn;
  226. cf_new->sockindex = cf_at->sockindex;
  227. pnext = &cf_new->next;
  228. cf_new = cf_new->next;
  229. } while(cf_new);
  230. *pnext = tail;
  231. }
  232. bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
  233. struct Curl_cfilter *discard,
  234. struct Curl_easy *data,
  235. bool destroy_always)
  236. {
  237. struct Curl_cfilter **pprev = &cf->next;
  238. bool found = FALSE;
  239. /* remove from sub-chain and destroy */
  240. DEBUGASSERT(cf);
  241. while(*pprev) {
  242. if(*pprev == cf) {
  243. *pprev = discard->next;
  244. discard->next = NULL;
  245. found = TRUE;
  246. break;
  247. }
  248. pprev = &((*pprev)->next);
  249. }
  250. if(found || destroy_always) {
  251. discard->next = NULL;
  252. discard->cft->destroy(discard, data);
  253. free(discard);
  254. }
  255. return found;
  256. }
  257. CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
  258. struct Curl_easy *data,
  259. bool blocking, bool *done)
  260. {
  261. if(cf)
  262. return cf->cft->do_connect(cf, data, blocking, done);
  263. return CURLE_FAILED_INIT;
  264. }
  265. void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  266. {
  267. if(cf)
  268. cf->cft->do_close(cf, data);
  269. }
  270. int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
  271. struct Curl_easy *data,
  272. curl_socket_t *socks)
  273. {
  274. if(cf)
  275. return cf->cft->get_select_socks(cf, data, socks);
  276. return 0;
  277. }
  278. ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  279. const void *buf, size_t len, CURLcode *err)
  280. {
  281. if(cf)
  282. return cf->cft->do_send(cf, data, buf, len, err);
  283. *err = CURLE_SEND_ERROR;
  284. return -1;
  285. }
  286. ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  287. char *buf, size_t len, CURLcode *err)
  288. {
  289. if(cf)
  290. return cf->cft->do_recv(cf, data, buf, len, err);
  291. *err = CURLE_RECV_ERROR;
  292. return -1;
  293. }
  294. CURLcode Curl_conn_connect(struct Curl_easy *data,
  295. int sockindex,
  296. bool blocking,
  297. bool *done)
  298. {
  299. struct Curl_cfilter *cf;
  300. CURLcode result = CURLE_OK;
  301. DEBUGASSERT(data);
  302. DEBUGASSERT(data->conn);
  303. cf = data->conn->cfilter[sockindex];
  304. DEBUGASSERT(cf);
  305. if(!cf)
  306. return CURLE_FAILED_INIT;
  307. *done = cf->connected;
  308. if(!*done) {
  309. result = cf->cft->do_connect(cf, data, blocking, done);
  310. if(!result && *done) {
  311. Curl_conn_ev_update_info(data, data->conn);
  312. conn_report_connect_stats(data, data->conn);
  313. data->conn->keepalive = Curl_now();
  314. }
  315. else if(result) {
  316. conn_report_connect_stats(data, data->conn);
  317. }
  318. }
  319. return result;
  320. }
  321. bool Curl_conn_is_connected(struct connectdata *conn, int sockindex)
  322. {
  323. struct Curl_cfilter *cf;
  324. cf = conn->cfilter[sockindex];
  325. return cf && cf->connected;
  326. }
  327. bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex)
  328. {
  329. struct Curl_cfilter *cf;
  330. cf = data->conn->cfilter[sockindex];
  331. while(cf) {
  332. if(cf->connected)
  333. return TRUE;
  334. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  335. return FALSE;
  336. cf = cf->next;
  337. }
  338. return FALSE;
  339. }
  340. bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf)
  341. {
  342. for(; cf; cf = cf->next) {
  343. if(cf->cft->flags & CF_TYPE_SSL)
  344. return TRUE;
  345. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  346. return FALSE;
  347. }
  348. return FALSE;
  349. }
  350. bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex)
  351. {
  352. return conn? Curl_conn_cf_is_ssl(conn->cfilter[sockindex]) : FALSE;
  353. }
  354. bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex)
  355. {
  356. struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
  357. for(; cf; cf = cf->next) {
  358. if(cf->cft->flags & CF_TYPE_MULTIPLEX)
  359. return TRUE;
  360. if(cf->cft->flags & CF_TYPE_IP_CONNECT
  361. || cf->cft->flags & CF_TYPE_SSL)
  362. return FALSE;
  363. }
  364. return FALSE;
  365. }
  366. bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
  367. {
  368. struct Curl_cfilter *cf;
  369. (void)data;
  370. DEBUGASSERT(data);
  371. DEBUGASSERT(data->conn);
  372. cf = data->conn->cfilter[sockindex];
  373. while(cf && !cf->connected) {
  374. cf = cf->next;
  375. }
  376. if(cf) {
  377. return cf->cft->has_data_pending(cf, data);
  378. }
  379. return FALSE;
  380. }
  381. int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
  382. curl_socket_t *socks)
  383. {
  384. struct Curl_cfilter *cf;
  385. DEBUGASSERT(data);
  386. DEBUGASSERT(data->conn);
  387. cf = data->conn->cfilter[sockindex];
  388. /* if the next one is not yet connected, that's the one we want */
  389. while(cf && cf->next && !cf->next->connected)
  390. cf = cf->next;
  391. if(cf) {
  392. return cf->cft->get_select_socks(cf, data, socks);
  393. }
  394. return GETSOCK_BLANK;
  395. }
  396. void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
  397. const char **phost, const char **pdisplay_host,
  398. int *pport)
  399. {
  400. struct Curl_cfilter *cf;
  401. DEBUGASSERT(data->conn);
  402. cf = data->conn->cfilter[sockindex];
  403. if(cf) {
  404. cf->cft->get_host(cf, data, phost, pdisplay_host, pport);
  405. }
  406. else {
  407. /* Some filter ask during shutdown for this, mainly for debugging
  408. * purposes. We hand out the defaults, however this is not always
  409. * accurate, as the connection might be tunneled, etc. But all that
  410. * state is already gone here. */
  411. *phost = data->conn->host.name;
  412. *pdisplay_host = data->conn->host.dispname;
  413. *pport = data->conn->remote_port;
  414. }
  415. }
  416. CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
  417. struct Curl_easy *data,
  418. int event, int arg1, void *arg2)
  419. {
  420. (void)cf;
  421. (void)data;
  422. (void)event;
  423. (void)arg1;
  424. (void)arg2;
  425. return CURLE_OK;
  426. }
  427. CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
  428. struct Curl_easy *data,
  429. bool ignore_result,
  430. int event, int arg1, void *arg2)
  431. {
  432. CURLcode result = CURLE_OK;
  433. for(; cf; cf = cf->next) {
  434. if(Curl_cf_def_cntrl == cf->cft->cntrl)
  435. continue;
  436. result = cf->cft->cntrl(cf, data, event, arg1, arg2);
  437. if(!ignore_result && result)
  438. break;
  439. }
  440. return result;
  441. }
  442. curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
  443. struct Curl_easy *data)
  444. {
  445. curl_socket_t sock;
  446. if(cf && !cf->cft->query(cf, data, CF_QUERY_SOCKET, NULL, &sock))
  447. return sock;
  448. return CURL_SOCKET_BAD;
  449. }
  450. curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
  451. {
  452. struct Curl_cfilter *cf;
  453. cf = data->conn? data->conn->cfilter[sockindex] : NULL;
  454. /* if the top filter has not connected, ask it (and its sub-filters)
  455. * for the socket. Otherwise conn->sock[sockindex] should have it.
  456. */
  457. if(cf && !cf->connected)
  458. return Curl_conn_cf_get_socket(cf, data);
  459. return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
  460. }
  461. static CURLcode cf_cntrl_all(struct connectdata *conn,
  462. struct Curl_easy *data,
  463. bool ignore_result,
  464. int event, int arg1, void *arg2)
  465. {
  466. CURLcode result = CURLE_OK;
  467. size_t i;
  468. for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
  469. result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
  470. event, arg1, arg2);
  471. if(!ignore_result && result)
  472. break;
  473. }
  474. return result;
  475. }
  476. void Curl_conn_ev_data_attach(struct connectdata *conn,
  477. struct Curl_easy *data)
  478. {
  479. cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_ATTACH, 0, NULL);
  480. }
  481. void Curl_conn_ev_data_detach(struct connectdata *conn,
  482. struct Curl_easy *data)
  483. {
  484. cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_DETACH, 0, NULL);
  485. }
  486. CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
  487. {
  488. return cf_cntrl_all(data->conn, data, FALSE,
  489. CF_CTRL_DATA_SETUP, 0, NULL);
  490. }
  491. CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data)
  492. {
  493. return cf_cntrl_all(data->conn, data, FALSE,
  494. CF_CTRL_DATA_IDLE, 0, NULL);
  495. }
  496. /**
  497. * Notify connection filters that the transfer represented by `data`
  498. * is donw with sending data (e.g. has uploaded everything).
  499. */
  500. void Curl_conn_ev_data_done_send(struct Curl_easy *data)
  501. {
  502. cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE_SEND, 0, NULL);
  503. }
  504. /**
  505. * Notify connection filters that the transfer represented by `data`
  506. * is finished - eventually premature, e.g. before being complete.
  507. */
  508. void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature)
  509. {
  510. cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE, premature, NULL);
  511. }
  512. CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause)
  513. {
  514. return cf_cntrl_all(data->conn, data, FALSE,
  515. CF_CTRL_DATA_PAUSE, do_pause, NULL);
  516. }
  517. void Curl_conn_ev_update_info(struct Curl_easy *data,
  518. struct connectdata *conn)
  519. {
  520. cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
  521. }
  522. /**
  523. * Update connection statistics
  524. */
  525. static void conn_report_connect_stats(struct Curl_easy *data,
  526. struct connectdata *conn)
  527. {
  528. struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
  529. if(cf) {
  530. struct curltime connected;
  531. struct curltime appconnected;
  532. memset(&connected, 0, sizeof(connected));
  533. cf->cft->query(cf, data, CF_QUERY_TIMER_CONNECT, NULL, &connected);
  534. if(connected.tv_sec || connected.tv_usec)
  535. Curl_pgrsTimeWas(data, TIMER_CONNECT, connected);
  536. memset(&appconnected, 0, sizeof(appconnected));
  537. cf->cft->query(cf, data, CF_QUERY_TIMER_APPCONNECT, NULL, &appconnected);
  538. if(appconnected.tv_sec || appconnected.tv_usec)
  539. Curl_pgrsTimeWas(data, TIMER_APPCONNECT, appconnected);
  540. }
  541. }
  542. bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
  543. bool *input_pending)
  544. {
  545. struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
  546. return cf && !cf->conn->bits.close &&
  547. cf->cft->is_alive(cf, data, input_pending);
  548. }
  549. CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
  550. struct connectdata *conn,
  551. int sockindex)
  552. {
  553. struct Curl_cfilter *cf = conn->cfilter[sockindex];
  554. return cf? cf->cft->keep_alive(cf, data) : CURLE_OK;
  555. }
  556. size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
  557. struct connectdata *conn,
  558. int sockindex)
  559. {
  560. CURLcode result;
  561. int n = 0;
  562. struct Curl_cfilter *cf = conn->cfilter[sockindex];
  563. result = cf? cf->cft->query(cf, data, CF_QUERY_MAX_CONCURRENT,
  564. &n, NULL) : CURLE_UNKNOWN_OPTION;
  565. return (result || n <= 0)? 1 : (size_t)n;
  566. }