select.c 20 KB

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