select.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  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. #if !defined(HAVE_SELECT) && !defined(HAVE_POLL)
  26. #error "We cannot compile without select() or poll() support."
  27. #endif
  28. #include <limits.h>
  29. #ifdef HAVE_SYS_SELECT_H
  30. #include <sys/select.h>
  31. #elif defined(HAVE_UNISTD_H)
  32. #include <unistd.h>
  33. #endif
  34. #include <curl/curl.h>
  35. #include "urldata.h"
  36. #include "connect.h"
  37. #include "select.h"
  38. #include "curl_trc.h"
  39. #include "curlx/timediff.h"
  40. #include "curlx/wait.h"
  41. #include "curlx/warnless.h"
  42. /* The last 2 #include files should be in this order */
  43. #include "curl_memory.h"
  44. #include "memdebug.h"
  45. #ifndef HAVE_POLL
  46. /*
  47. * This is a wrapper around select() to aid in Windows compatibility. A
  48. * negative timeout value makes this function wait indefinitely, unless no
  49. * valid file descriptor is given, when this happens the negative timeout is
  50. * ignored and the function times out immediately.
  51. *
  52. * Return values:
  53. * -1 = system call error or fd >= FD_SETSIZE
  54. * 0 = timeout
  55. * N = number of signalled file descriptors
  56. */
  57. static int our_select(curl_socket_t maxfd, /* highest socket number */
  58. fd_set *fds_read, /* sockets ready for reading */
  59. fd_set *fds_write, /* sockets ready for writing */
  60. fd_set *fds_err, /* sockets with errors */
  61. timediff_t timeout_ms) /* milliseconds to wait */
  62. {
  63. struct timeval pending_tv;
  64. struct timeval *ptimeout;
  65. #ifdef USE_WINSOCK
  66. /* Winsock select() cannot handle zero events. See the comment below. */
  67. if((!fds_read || fds_read->fd_count == 0) &&
  68. (!fds_write || fds_write->fd_count == 0) &&
  69. (!fds_err || fds_err->fd_count == 0)) {
  70. /* no sockets, just wait */
  71. return curlx_wait_ms(timeout_ms);
  72. }
  73. #endif
  74. ptimeout = curlx_mstotv(&pending_tv, timeout_ms);
  75. #ifdef USE_WINSOCK
  76. /* Winsock select() must not be called with an fd_set that contains zero
  77. fd flags, or it will return WSAEINVAL. But, it also cannot be called
  78. with no fd_sets at all! From the documentation:
  79. Any two of the parameters, readfds, writefds, or exceptfds, can be
  80. given as null. At least one must be non-null, and any non-null
  81. descriptor set must contain at least one handle to a socket.
  82. It is unclear why Winsock does not just handle this for us instead of
  83. calling this an error. Luckily, with Winsock, we can _also_ ask how
  84. many bits are set on an fd_set. So, let's just check it beforehand.
  85. */
  86. return select((int)maxfd + 1,
  87. fds_read && fds_read->fd_count ? fds_read : NULL,
  88. fds_write && fds_write->fd_count ? fds_write : NULL,
  89. fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
  90. #else
  91. return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
  92. #endif
  93. }
  94. #endif
  95. /*
  96. * Wait for read or write events on a set of file descriptors. It uses poll()
  97. * when poll() is available, in order to avoid limits with FD_SETSIZE,
  98. * otherwise select() is used. An error is returned if select() is being used
  99. * and a file descriptor is too large for FD_SETSIZE.
  100. *
  101. * A negative timeout value makes this function wait indefinitely, unless no
  102. * valid file descriptor is given, when this happens the negative timeout is
  103. * ignored and the function times out immediately.
  104. *
  105. * Return values:
  106. * -1 = system call error or fd >= FD_SETSIZE
  107. * 0 = timeout
  108. * [bitmask] = action as described below
  109. *
  110. * CURL_CSELECT_IN - first socket is readable
  111. * CURL_CSELECT_IN2 - second socket is readable
  112. * CURL_CSELECT_OUT - write socket is writable
  113. * CURL_CSELECT_ERR - an error condition occurred
  114. */
  115. int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
  116. curl_socket_t readfd1,
  117. curl_socket_t writefd, /* socket to write to */
  118. timediff_t timeout_ms) /* milliseconds to wait */
  119. {
  120. struct pollfd pfd[3];
  121. int num;
  122. int r;
  123. if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
  124. (writefd == CURL_SOCKET_BAD)) {
  125. /* no sockets, just wait */
  126. return curlx_wait_ms(timeout_ms);
  127. }
  128. /* Avoid initial timestamp, avoid curlx_now() call, when elapsed
  129. time in this function does not need to be measured. This happens
  130. when function is called with a zero timeout or a negative timeout
  131. value indicating a blocking call should be performed. */
  132. num = 0;
  133. if(readfd0 != CURL_SOCKET_BAD) {
  134. pfd[num].fd = readfd0;
  135. pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
  136. pfd[num].revents = 0;
  137. num++;
  138. }
  139. if(readfd1 != CURL_SOCKET_BAD) {
  140. pfd[num].fd = readfd1;
  141. pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
  142. pfd[num].revents = 0;
  143. num++;
  144. }
  145. if(writefd != CURL_SOCKET_BAD) {
  146. pfd[num].fd = writefd;
  147. pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI;
  148. pfd[num].revents = 0;
  149. num++;
  150. }
  151. r = Curl_poll(pfd, (unsigned int)num, timeout_ms);
  152. if(r <= 0)
  153. return r;
  154. r = 0;
  155. num = 0;
  156. if(readfd0 != CURL_SOCKET_BAD) {
  157. if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
  158. r |= CURL_CSELECT_IN;
  159. if(pfd[num].revents & (POLLPRI|POLLNVAL))
  160. r |= CURL_CSELECT_ERR;
  161. num++;
  162. }
  163. if(readfd1 != CURL_SOCKET_BAD) {
  164. if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
  165. r |= CURL_CSELECT_IN2;
  166. if(pfd[num].revents & (POLLPRI|POLLNVAL))
  167. r |= CURL_CSELECT_ERR;
  168. num++;
  169. }
  170. if(writefd != CURL_SOCKET_BAD) {
  171. if(pfd[num].revents & (POLLWRNORM|POLLOUT))
  172. r |= CURL_CSELECT_OUT;
  173. if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL))
  174. r |= CURL_CSELECT_ERR;
  175. }
  176. return r;
  177. }
  178. /*
  179. * This is a wrapper around poll(). If poll() does not exist, then
  180. * select() is used instead. An error is returned if select() is
  181. * being used and a file descriptor is too large for FD_SETSIZE.
  182. * A negative timeout value makes this function wait indefinitely,
  183. * unless no valid file descriptor is given, when this happens the
  184. * negative timeout is ignored and the function times out immediately.
  185. *
  186. * Return values:
  187. * -1 = system call error or fd >= FD_SETSIZE
  188. * 0 = timeout
  189. * N = number of structures with non zero revent fields
  190. */
  191. int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
  192. {
  193. #ifdef HAVE_POLL
  194. int pending_ms;
  195. #else
  196. fd_set fds_read;
  197. fd_set fds_write;
  198. fd_set fds_err;
  199. curl_socket_t maxfd;
  200. #endif
  201. bool fds_none = TRUE;
  202. unsigned int i;
  203. int r;
  204. if(ufds) {
  205. for(i = 0; i < nfds; i++) {
  206. if(ufds[i].fd != CURL_SOCKET_BAD) {
  207. fds_none = FALSE;
  208. break;
  209. }
  210. }
  211. }
  212. if(fds_none) {
  213. /* no sockets, just wait */
  214. return curlx_wait_ms(timeout_ms);
  215. }
  216. /* Avoid initial timestamp, avoid curlx_now() call, when elapsed
  217. time in this function does not need to be measured. This happens
  218. when function is called with a zero timeout or a negative timeout
  219. value indicating a blocking call should be performed. */
  220. #ifdef HAVE_POLL
  221. /* prevent overflow, timeout_ms is typecast to int. */
  222. #if TIMEDIFF_T_MAX > INT_MAX
  223. if(timeout_ms > INT_MAX)
  224. timeout_ms = INT_MAX;
  225. #endif
  226. if(timeout_ms > 0)
  227. pending_ms = (int)timeout_ms;
  228. else if(timeout_ms < 0)
  229. pending_ms = -1;
  230. else
  231. pending_ms = 0;
  232. r = poll(ufds, nfds, pending_ms);
  233. if(r <= 0) {
  234. if((r == -1) && (SOCKERRNO == SOCKEINTR))
  235. /* make EINTR from select or poll not a "lethal" error */
  236. r = 0;
  237. return r;
  238. }
  239. for(i = 0; i < nfds; i++) {
  240. if(ufds[i].fd == CURL_SOCKET_BAD)
  241. continue;
  242. if(ufds[i].revents & POLLHUP)
  243. ufds[i].revents |= POLLIN;
  244. if(ufds[i].revents & POLLERR)
  245. ufds[i].revents |= POLLIN|POLLOUT;
  246. }
  247. #else /* HAVE_POLL */
  248. FD_ZERO(&fds_read);
  249. FD_ZERO(&fds_write);
  250. FD_ZERO(&fds_err);
  251. maxfd = (curl_socket_t)-1;
  252. for(i = 0; i < nfds; i++) {
  253. ufds[i].revents = 0;
  254. if(ufds[i].fd == CURL_SOCKET_BAD)
  255. continue;
  256. VERIFY_SOCK(ufds[i].fd);
  257. if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
  258. POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
  259. if(ufds[i].fd > maxfd)
  260. maxfd = ufds[i].fd;
  261. if(ufds[i].events & (POLLRDNORM|POLLIN))
  262. FD_SET(ufds[i].fd, &fds_read);
  263. if(ufds[i].events & (POLLWRNORM|POLLOUT))
  264. FD_SET(ufds[i].fd, &fds_write);
  265. if(ufds[i].events & (POLLRDBAND|POLLPRI))
  266. FD_SET(ufds[i].fd, &fds_err);
  267. }
  268. }
  269. /*
  270. Note also that Winsock ignores the first argument, so we do not worry
  271. about the fact that maxfd is computed incorrectly with Winsock (since
  272. curl_socket_t is unsigned in such cases and thus -1 is the largest
  273. value).
  274. */
  275. r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
  276. if(r <= 0) {
  277. if((r == -1) && (SOCKERRNO == SOCKEINTR))
  278. /* make EINTR from select or poll not a "lethal" error */
  279. r = 0;
  280. return r;
  281. }
  282. r = 0;
  283. for(i = 0; i < nfds; i++) {
  284. ufds[i].revents = 0;
  285. if(ufds[i].fd == CURL_SOCKET_BAD)
  286. continue;
  287. if(FD_ISSET(ufds[i].fd, &fds_read)) {
  288. if(ufds[i].events & POLLRDNORM)
  289. ufds[i].revents |= POLLRDNORM;
  290. if(ufds[i].events & POLLIN)
  291. ufds[i].revents |= POLLIN;
  292. }
  293. if(FD_ISSET(ufds[i].fd, &fds_write)) {
  294. if(ufds[i].events & POLLWRNORM)
  295. ufds[i].revents |= POLLWRNORM;
  296. if(ufds[i].events & POLLOUT)
  297. ufds[i].revents |= POLLOUT;
  298. }
  299. if(FD_ISSET(ufds[i].fd, &fds_err)) {
  300. if(ufds[i].events & POLLRDBAND)
  301. ufds[i].revents |= POLLRDBAND;
  302. if(ufds[i].events & POLLPRI)
  303. ufds[i].revents |= POLLPRI;
  304. }
  305. if(ufds[i].revents)
  306. r++;
  307. }
  308. #endif /* HAVE_POLL */
  309. return r;
  310. }
  311. void Curl_pollfds_init(struct curl_pollfds *cpfds,
  312. struct pollfd *static_pfds,
  313. unsigned int static_count)
  314. {
  315. DEBUGASSERT(cpfds);
  316. memset(cpfds, 0, sizeof(*cpfds));
  317. if(static_pfds && static_count) {
  318. cpfds->pfds = static_pfds;
  319. cpfds->count = static_count;
  320. }
  321. }
  322. void Curl_pollfds_reset(struct curl_pollfds *cpfds)
  323. {
  324. cpfds->n = 0;
  325. }
  326. void Curl_pollfds_cleanup(struct curl_pollfds *cpfds)
  327. {
  328. DEBUGASSERT(cpfds);
  329. if(cpfds->allocated_pfds) {
  330. free(cpfds->pfds);
  331. }
  332. memset(cpfds, 0, sizeof(*cpfds));
  333. }
  334. static CURLcode cpfds_increase(struct curl_pollfds *cpfds, unsigned int inc)
  335. {
  336. struct pollfd *new_fds;
  337. unsigned int new_count = cpfds->count + inc;
  338. new_fds = calloc(new_count, sizeof(struct pollfd));
  339. if(!new_fds)
  340. return CURLE_OUT_OF_MEMORY;
  341. memcpy(new_fds, cpfds->pfds, cpfds->count * sizeof(struct pollfd));
  342. if(cpfds->allocated_pfds)
  343. free(cpfds->pfds);
  344. cpfds->pfds = new_fds;
  345. cpfds->count = new_count;
  346. cpfds->allocated_pfds = TRUE;
  347. return CURLE_OK;
  348. }
  349. static CURLcode cpfds_add_sock(struct curl_pollfds *cpfds,
  350. curl_socket_t sock, short events, bool fold)
  351. {
  352. int i;
  353. if(fold && cpfds->n <= INT_MAX) {
  354. for(i = (int)cpfds->n - 1; i >= 0; --i) {
  355. if(sock == cpfds->pfds[i].fd) {
  356. cpfds->pfds[i].events |= events;
  357. return CURLE_OK;
  358. }
  359. }
  360. }
  361. /* not folded, add new entry */
  362. if(cpfds->n >= cpfds->count) {
  363. if(cpfds_increase(cpfds, 100))
  364. return CURLE_OUT_OF_MEMORY;
  365. }
  366. cpfds->pfds[cpfds->n].fd = sock;
  367. cpfds->pfds[cpfds->n].events = events;
  368. ++cpfds->n;
  369. return CURLE_OK;
  370. }
  371. CURLcode Curl_pollfds_add_sock(struct curl_pollfds *cpfds,
  372. curl_socket_t sock, short events)
  373. {
  374. return cpfds_add_sock(cpfds, sock, events, FALSE);
  375. }
  376. CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds,
  377. struct easy_pollset *ps)
  378. {
  379. size_t i;
  380. DEBUGASSERT(cpfds);
  381. DEBUGASSERT(ps);
  382. for(i = 0; i < ps->n; i++) {
  383. short events = 0;
  384. if(ps->actions[i] & CURL_POLL_IN)
  385. events |= POLLIN;
  386. if(ps->actions[i] & CURL_POLL_OUT)
  387. events |= POLLOUT;
  388. if(events) {
  389. if(cpfds_add_sock(cpfds, ps->sockets[i], events, TRUE))
  390. return CURLE_OUT_OF_MEMORY;
  391. }
  392. }
  393. return CURLE_OK;
  394. }
  395. void Curl_waitfds_init(struct Curl_waitfds *cwfds,
  396. struct curl_waitfd *static_wfds,
  397. unsigned int static_count)
  398. {
  399. DEBUGASSERT(cwfds);
  400. DEBUGASSERT(static_wfds || !static_count);
  401. memset(cwfds, 0, sizeof(*cwfds));
  402. cwfds->wfds = static_wfds;
  403. cwfds->count = static_count;
  404. }
  405. static unsigned int cwfds_add_sock(struct Curl_waitfds *cwfds,
  406. curl_socket_t sock, short events)
  407. {
  408. int i;
  409. if(!cwfds->wfds) {
  410. DEBUGASSERT(!cwfds->count && !cwfds->n);
  411. return 1;
  412. }
  413. if(cwfds->n <= INT_MAX) {
  414. for(i = (int)cwfds->n - 1; i >= 0; --i) {
  415. if(sock == cwfds->wfds[i].fd) {
  416. cwfds->wfds[i].events |= events;
  417. return 0;
  418. }
  419. }
  420. }
  421. /* not folded, add new entry */
  422. if(cwfds->n < cwfds->count) {
  423. cwfds->wfds[cwfds->n].fd = sock;
  424. cwfds->wfds[cwfds->n].events = events;
  425. ++cwfds->n;
  426. }
  427. return 1;
  428. }
  429. unsigned int Curl_waitfds_add_ps(struct Curl_waitfds *cwfds,
  430. struct easy_pollset *ps)
  431. {
  432. size_t i;
  433. unsigned int need = 0;
  434. DEBUGASSERT(cwfds);
  435. DEBUGASSERT(ps);
  436. for(i = 0; i < ps->n; i++) {
  437. short events = 0;
  438. if(ps->actions[i] & CURL_POLL_IN)
  439. events |= CURL_WAIT_POLLIN;
  440. if(ps->actions[i] & CURL_POLL_OUT)
  441. events |= CURL_WAIT_POLLOUT;
  442. if(events)
  443. need += cwfds_add_sock(cwfds, ps->sockets[i], events);
  444. }
  445. return need;
  446. }
  447. void Curl_pollset_reset(struct easy_pollset *ps)
  448. {
  449. unsigned int i;
  450. ps->n = 0;
  451. #ifdef DEBUGBUILD
  452. DEBUGASSERT(ps->init == CURL_EASY_POLLSET_MAGIC);
  453. #endif
  454. DEBUGASSERT(ps->count);
  455. for(i = 0; i < ps->count; i++)
  456. ps->sockets[i] = CURL_SOCKET_BAD;
  457. memset(ps->actions, 0, ps->count * sizeof(ps->actions[0]));
  458. }
  459. void Curl_pollset_init(struct easy_pollset *ps)
  460. {
  461. #ifdef DEBUGBUILD
  462. ps->init = CURL_EASY_POLLSET_MAGIC;
  463. #endif
  464. ps->sockets = ps->def_sockets;
  465. ps->actions = ps->def_actions;
  466. ps->count = CURL_ARRAYSIZE(ps->def_sockets);
  467. ps->n = 0;
  468. Curl_pollset_reset(ps);
  469. }
  470. struct easy_pollset *Curl_pollset_create(void)
  471. {
  472. struct easy_pollset *ps = calloc(1, sizeof(*ps));
  473. if(ps)
  474. Curl_pollset_init(ps);
  475. return ps;
  476. }
  477. void Curl_pollset_cleanup(struct easy_pollset *ps)
  478. {
  479. #ifdef DEBUGBUILD
  480. DEBUGASSERT(ps->init == CURL_EASY_POLLSET_MAGIC);
  481. #endif
  482. if(ps->sockets != ps->def_sockets) {
  483. free(ps->sockets);
  484. ps->sockets = ps->def_sockets;
  485. }
  486. if(ps->actions != ps->def_actions) {
  487. free(ps->actions);
  488. ps->actions = ps->def_actions;
  489. }
  490. ps->count = CURL_ARRAYSIZE(ps->def_sockets);
  491. Curl_pollset_reset(ps);
  492. }
  493. void Curl_pollset_move(struct easy_pollset *to, struct easy_pollset *from)
  494. {
  495. Curl_pollset_cleanup(to); /* deallocate anything in to */
  496. if(from->sockets != from->def_sockets) {
  497. DEBUGASSERT(from->actions != from->def_actions);
  498. to->sockets = from->sockets;
  499. to->actions = from->actions;
  500. to->count = from->count;
  501. to->n = from->n;
  502. Curl_pollset_init(from);
  503. }
  504. else {
  505. DEBUGASSERT(to->sockets == to->def_sockets);
  506. DEBUGASSERT(to->actions == to->def_actions);
  507. memcpy(to->sockets, from->sockets, to->count * sizeof(to->sockets[0]));
  508. memcpy(to->actions, from->actions, to->count * sizeof(to->actions[0]));
  509. to->n = from->n;
  510. Curl_pollset_init(from);
  511. }
  512. }
  513. /**
  514. *
  515. */
  516. CURLcode Curl_pollset_change(struct Curl_easy *data,
  517. struct easy_pollset *ps, curl_socket_t sock,
  518. int add_flags, int remove_flags)
  519. {
  520. unsigned int i;
  521. #ifdef DEBUGBUILD
  522. DEBUGASSERT(ps->init == CURL_EASY_POLLSET_MAGIC);
  523. #endif
  524. (void)data;
  525. DEBUGASSERT(VALID_SOCK(sock));
  526. if(!VALID_SOCK(sock))
  527. return CURLE_BAD_FUNCTION_ARGUMENT;
  528. DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
  529. DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
  530. DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
  531. for(i = 0; i < ps->n; ++i) {
  532. if(ps->sockets[i] == sock) {
  533. ps->actions[i] &= (unsigned char)(~remove_flags);
  534. ps->actions[i] |= (unsigned char)add_flags;
  535. /* all gone? remove socket */
  536. if(!ps->actions[i]) {
  537. if((i + 1) < ps->n) {
  538. memmove(&ps->sockets[i], &ps->sockets[i + 1],
  539. (ps->n - (i + 1)) * sizeof(ps->sockets[0]));
  540. memmove(&ps->actions[i], &ps->actions[i + 1],
  541. (ps->n - (i + 1)) * sizeof(ps->actions[0]));
  542. }
  543. --ps->n;
  544. }
  545. return CURLE_OK;
  546. }
  547. }
  548. /* not present */
  549. if(add_flags) {
  550. if(i >= ps->count) { /* need to grow */
  551. unsigned int new_count = CURLMAX(ps->count * 2, 8);
  552. curl_socket_t *nsockets;
  553. unsigned char *nactions;
  554. CURL_TRC_M(data, "growing pollset capacity from %u to %u",
  555. ps->count, new_count);
  556. if(new_count <= ps->count)
  557. return CURLE_OUT_OF_MEMORY;
  558. nsockets = calloc(new_count, sizeof(nsockets[0]));
  559. if(!nsockets)
  560. return CURLE_OUT_OF_MEMORY;
  561. nactions = calloc(new_count, sizeof(nactions[0]));
  562. if(!nactions) {
  563. free(nsockets);
  564. return CURLE_OUT_OF_MEMORY;
  565. }
  566. memcpy(nsockets, ps->sockets, ps->count * sizeof(ps->sockets[0]));
  567. memcpy(nactions, ps->actions, ps->count * sizeof(ps->actions[0]));
  568. if(ps->sockets != ps->def_sockets)
  569. free(ps->sockets);
  570. ps->sockets = nsockets;
  571. if(ps->actions != ps->def_actions)
  572. free(ps->actions);
  573. ps->actions = nactions;
  574. ps->count = new_count;
  575. }
  576. DEBUGASSERT(i < ps->count);
  577. if(i < ps->count) {
  578. ps->sockets[i] = sock;
  579. ps->actions[i] = (unsigned char)add_flags;
  580. ps->n = i + 1;
  581. }
  582. }
  583. return CURLE_OK;
  584. }
  585. CURLcode Curl_pollset_set(struct Curl_easy *data,
  586. struct easy_pollset *ps, curl_socket_t sock,
  587. bool do_in, bool do_out)
  588. {
  589. return Curl_pollset_change(data, ps, sock,
  590. (do_in ? CURL_POLL_IN : 0)|
  591. (do_out ? CURL_POLL_OUT : 0),
  592. (!do_in ? CURL_POLL_IN : 0)|
  593. (!do_out ? CURL_POLL_OUT : 0));
  594. }
  595. int Curl_pollset_poll(struct Curl_easy *data,
  596. struct easy_pollset *ps,
  597. timediff_t timeout_ms)
  598. {
  599. struct pollfd *pfds;
  600. unsigned int i, npfds;
  601. int result;
  602. (void)data;
  603. DEBUGASSERT(data);
  604. DEBUGASSERT(data->conn);
  605. if(!ps->n)
  606. return curlx_wait_ms(timeout_ms);
  607. pfds = calloc(ps->n, sizeof(*pfds));
  608. if(!pfds)
  609. return -1;
  610. npfds = 0;
  611. for(i = 0; i < ps->n; ++i) {
  612. short events = 0;
  613. if(ps->actions[i] & CURL_POLL_IN) {
  614. events |= POLLIN;
  615. }
  616. if(ps->actions[i] & CURL_POLL_OUT) {
  617. events |= POLLOUT;
  618. }
  619. if(events) {
  620. pfds[npfds].fd = ps->sockets[i];
  621. pfds[npfds].events = events;
  622. ++npfds;
  623. }
  624. }
  625. result = Curl_poll(pfds, npfds, timeout_ms);
  626. free(pfds);
  627. return result;
  628. }
  629. void Curl_pollset_check(struct Curl_easy *data,
  630. struct easy_pollset *ps, curl_socket_t sock,
  631. bool *pwant_read, bool *pwant_write)
  632. {
  633. unsigned int i;
  634. (void)data;
  635. DEBUGASSERT(VALID_SOCK(sock));
  636. for(i = 0; i < ps->n; ++i) {
  637. if(ps->sockets[i] == sock) {
  638. *pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
  639. *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
  640. return;
  641. }
  642. }
  643. *pwant_read = *pwant_write = FALSE;
  644. }
  645. bool Curl_pollset_want_read(struct Curl_easy *data,
  646. struct easy_pollset *ps,
  647. curl_socket_t sock)
  648. {
  649. unsigned int i;
  650. (void)data;
  651. for(i = 0; i < ps->n; ++i) {
  652. if((ps->sockets[i] == sock) && (ps->actions[i] & CURL_POLL_IN))
  653. return TRUE;
  654. }
  655. return FALSE;
  656. }