2
0

select.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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. #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. #ifdef MSDOS
  35. #include <dos.h> /* delay() */
  36. #endif
  37. #include <curl/curl.h>
  38. #include "urldata.h"
  39. #include "connect.h"
  40. #include "select.h"
  41. #include "timediff.h"
  42. #include "warnless.h"
  43. /* The last 3 #include files should be in this order */
  44. #include "curl_printf.h"
  45. #include "curl_memory.h"
  46. #include "memdebug.h"
  47. /*
  48. * Internal function used for waiting a specific amount of ms in
  49. * Curl_socket_check() and Curl_poll() when no file descriptor is provided to
  50. * wait on, just being used to delay execution. Winsock select() and poll()
  51. * timeout mechanisms need a valid socket descriptor in a not null file
  52. * descriptor set to work. Waiting indefinitely with this function is not
  53. * allowed, a zero or negative timeout value will return immediately. Timeout
  54. * resolution, accuracy, as well as maximum supported value is system
  55. * dependent, neither factor is a critical issue for the intended use of this
  56. * function in the library.
  57. *
  58. * Return values:
  59. * -1 = system call error, or invalid timeout value
  60. * 0 = specified timeout has elapsed, or interrupted
  61. */
  62. int Curl_wait_ms(timediff_t timeout_ms)
  63. {
  64. int r = 0;
  65. if(!timeout_ms)
  66. return 0;
  67. if(timeout_ms < 0) {
  68. SET_SOCKERRNO(EINVAL);
  69. return -1;
  70. }
  71. #if defined(MSDOS)
  72. delay(timeout_ms);
  73. #elif defined(_WIN32)
  74. /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
  75. #if TIMEDIFF_T_MAX >= ULONG_MAX
  76. if(timeout_ms >= ULONG_MAX)
  77. timeout_ms = ULONG_MAX-1;
  78. /* do not use ULONG_MAX, because that is equal to INFINITE */
  79. #endif
  80. Sleep((ULONG)timeout_ms);
  81. #else
  82. /* avoid using poll() for this since it behaves incorrectly with no sockets
  83. on Apple operating systems */
  84. {
  85. struct timeval pending_tv;
  86. r = select(0, NULL, NULL, NULL, curlx_mstotv(&pending_tv, timeout_ms));
  87. }
  88. #endif /* _WIN32 */
  89. if(r) {
  90. if((r == -1) && (SOCKERRNO == EINTR))
  91. /* make EINTR from select or poll not a "lethal" error */
  92. r = 0;
  93. else
  94. r = -1;
  95. }
  96. return r;
  97. }
  98. #ifndef HAVE_POLL
  99. /*
  100. * This is a wrapper around select() to aid in Windows compatibility. A
  101. * 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. * N = number of signalled file descriptors
  109. */
  110. static int our_select(curl_socket_t maxfd, /* highest socket number */
  111. fd_set *fds_read, /* sockets ready for reading */
  112. fd_set *fds_write, /* sockets ready for writing */
  113. fd_set *fds_err, /* sockets with errors */
  114. timediff_t timeout_ms) /* milliseconds to wait */
  115. {
  116. struct timeval pending_tv;
  117. struct timeval *ptimeout;
  118. #ifdef USE_WINSOCK
  119. /* Winsock select() cannot handle zero events. See the comment below. */
  120. if((!fds_read || fds_read->fd_count == 0) &&
  121. (!fds_write || fds_write->fd_count == 0) &&
  122. (!fds_err || fds_err->fd_count == 0)) {
  123. /* no sockets, just wait */
  124. return Curl_wait_ms(timeout_ms);
  125. }
  126. #endif
  127. ptimeout = curlx_mstotv(&pending_tv, timeout_ms);
  128. #ifdef USE_WINSOCK
  129. /* Winsock select() must not be called with an fd_set that contains zero
  130. fd flags, or it will return WSAEINVAL. But, it also cannot be called
  131. with no fd_sets at all! From the documentation:
  132. Any two of the parameters, readfds, writefds, or exceptfds, can be
  133. given as null. At least one must be non-null, and any non-null
  134. descriptor set must contain at least one handle to a socket.
  135. It is unclear why Winsock does not just handle this for us instead of
  136. calling this an error. Luckily, with Winsock, we can _also_ ask how
  137. many bits are set on an fd_set. So, let's just check it beforehand.
  138. */
  139. return select((int)maxfd + 1,
  140. fds_read && fds_read->fd_count ? fds_read : NULL,
  141. fds_write && fds_write->fd_count ? fds_write : NULL,
  142. fds_err && fds_err->fd_count ? fds_err : NULL, ptimeout);
  143. #else
  144. return select((int)maxfd + 1, fds_read, fds_write, fds_err, ptimeout);
  145. #endif
  146. }
  147. #endif
  148. /*
  149. * Wait for read or write events on a set of file descriptors. It uses poll()
  150. * when poll() is available, in order to avoid limits with FD_SETSIZE,
  151. * otherwise select() is used. An error is returned if select() is being used
  152. * and a file descriptor is too large for FD_SETSIZE.
  153. *
  154. * A negative timeout value makes this function wait indefinitely, unless no
  155. * valid file descriptor is given, when this happens the negative timeout is
  156. * ignored and the function times out immediately.
  157. *
  158. * Return values:
  159. * -1 = system call error or fd >= FD_SETSIZE
  160. * 0 = timeout
  161. * [bitmask] = action as described below
  162. *
  163. * CURL_CSELECT_IN - first socket is readable
  164. * CURL_CSELECT_IN2 - second socket is readable
  165. * CURL_CSELECT_OUT - write socket is writable
  166. * CURL_CSELECT_ERR - an error condition occurred
  167. */
  168. int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
  169. curl_socket_t readfd1,
  170. curl_socket_t writefd, /* socket to write to */
  171. timediff_t timeout_ms) /* milliseconds to wait */
  172. {
  173. struct pollfd pfd[3];
  174. int num;
  175. int r;
  176. if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
  177. (writefd == CURL_SOCKET_BAD)) {
  178. /* no sockets, just wait */
  179. return Curl_wait_ms(timeout_ms);
  180. }
  181. /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
  182. time in this function does not need to be measured. This happens
  183. when function is called with a zero timeout or a negative timeout
  184. value indicating a blocking call should be performed. */
  185. num = 0;
  186. if(readfd0 != CURL_SOCKET_BAD) {
  187. pfd[num].fd = readfd0;
  188. pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
  189. pfd[num].revents = 0;
  190. num++;
  191. }
  192. if(readfd1 != CURL_SOCKET_BAD) {
  193. pfd[num].fd = readfd1;
  194. pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
  195. pfd[num].revents = 0;
  196. num++;
  197. }
  198. if(writefd != CURL_SOCKET_BAD) {
  199. pfd[num].fd = writefd;
  200. pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI;
  201. pfd[num].revents = 0;
  202. num++;
  203. }
  204. r = Curl_poll(pfd, (unsigned int)num, timeout_ms);
  205. if(r <= 0)
  206. return r;
  207. r = 0;
  208. num = 0;
  209. if(readfd0 != CURL_SOCKET_BAD) {
  210. if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
  211. r |= CURL_CSELECT_IN;
  212. if(pfd[num].revents & (POLLPRI|POLLNVAL))
  213. r |= CURL_CSELECT_ERR;
  214. num++;
  215. }
  216. if(readfd1 != CURL_SOCKET_BAD) {
  217. if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
  218. r |= CURL_CSELECT_IN2;
  219. if(pfd[num].revents & (POLLPRI|POLLNVAL))
  220. r |= CURL_CSELECT_ERR;
  221. num++;
  222. }
  223. if(writefd != CURL_SOCKET_BAD) {
  224. if(pfd[num].revents & (POLLWRNORM|POLLOUT))
  225. r |= CURL_CSELECT_OUT;
  226. if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL))
  227. r |= CURL_CSELECT_ERR;
  228. }
  229. return r;
  230. }
  231. /*
  232. * This is a wrapper around poll(). If poll() does not exist, then
  233. * select() is used instead. An error is returned if select() is
  234. * being used and a file descriptor is too large for FD_SETSIZE.
  235. * A negative timeout value makes this function wait indefinitely,
  236. * unless no valid file descriptor is given, when this happens the
  237. * negative timeout is ignored and the function times out immediately.
  238. *
  239. * Return values:
  240. * -1 = system call error or fd >= FD_SETSIZE
  241. * 0 = timeout
  242. * N = number of structures with non zero revent fields
  243. */
  244. int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
  245. {
  246. #ifdef HAVE_POLL
  247. int pending_ms;
  248. #else
  249. fd_set fds_read;
  250. fd_set fds_write;
  251. fd_set fds_err;
  252. curl_socket_t maxfd;
  253. #endif
  254. bool fds_none = TRUE;
  255. unsigned int i;
  256. int r;
  257. if(ufds) {
  258. for(i = 0; i < nfds; i++) {
  259. if(ufds[i].fd != CURL_SOCKET_BAD) {
  260. fds_none = FALSE;
  261. break;
  262. }
  263. }
  264. }
  265. if(fds_none) {
  266. /* no sockets, just wait */
  267. return Curl_wait_ms(timeout_ms);
  268. }
  269. /* Avoid initial timestamp, avoid Curl_now() call, when elapsed
  270. time in this function does not need to be measured. This happens
  271. when function is called with a zero timeout or a negative timeout
  272. value indicating a blocking call should be performed. */
  273. #ifdef HAVE_POLL
  274. /* prevent overflow, timeout_ms is typecast to int. */
  275. #if TIMEDIFF_T_MAX > INT_MAX
  276. if(timeout_ms > INT_MAX)
  277. timeout_ms = INT_MAX;
  278. #endif
  279. if(timeout_ms > 0)
  280. pending_ms = (int)timeout_ms;
  281. else if(timeout_ms < 0)
  282. pending_ms = -1;
  283. else
  284. pending_ms = 0;
  285. r = poll(ufds, nfds, pending_ms);
  286. if(r <= 0) {
  287. if((r == -1) && (SOCKERRNO == EINTR))
  288. /* make EINTR from select or poll not a "lethal" error */
  289. r = 0;
  290. return r;
  291. }
  292. for(i = 0; i < nfds; i++) {
  293. if(ufds[i].fd == CURL_SOCKET_BAD)
  294. continue;
  295. if(ufds[i].revents & POLLHUP)
  296. ufds[i].revents |= POLLIN;
  297. if(ufds[i].revents & POLLERR)
  298. ufds[i].revents |= POLLIN|POLLOUT;
  299. }
  300. #else /* HAVE_POLL */
  301. FD_ZERO(&fds_read);
  302. FD_ZERO(&fds_write);
  303. FD_ZERO(&fds_err);
  304. maxfd = (curl_socket_t)-1;
  305. for(i = 0; i < nfds; i++) {
  306. ufds[i].revents = 0;
  307. if(ufds[i].fd == CURL_SOCKET_BAD)
  308. continue;
  309. VERIFY_SOCK(ufds[i].fd);
  310. if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
  311. POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
  312. if(ufds[i].fd > maxfd)
  313. maxfd = ufds[i].fd;
  314. if(ufds[i].events & (POLLRDNORM|POLLIN))
  315. FD_SET(ufds[i].fd, &fds_read);
  316. if(ufds[i].events & (POLLWRNORM|POLLOUT))
  317. FD_SET(ufds[i].fd, &fds_write);
  318. if(ufds[i].events & (POLLRDBAND|POLLPRI))
  319. FD_SET(ufds[i].fd, &fds_err);
  320. }
  321. }
  322. /*
  323. Note also that Winsock ignores the first argument, so we do not worry
  324. about the fact that maxfd is computed incorrectly with Winsock (since
  325. curl_socket_t is unsigned in such cases and thus -1 is the largest
  326. value).
  327. */
  328. r = our_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
  329. if(r <= 0) {
  330. if((r == -1) && (SOCKERRNO == EINTR))
  331. /* make EINTR from select or poll not a "lethal" error */
  332. r = 0;
  333. return r;
  334. }
  335. r = 0;
  336. for(i = 0; i < nfds; i++) {
  337. ufds[i].revents = 0;
  338. if(ufds[i].fd == CURL_SOCKET_BAD)
  339. continue;
  340. if(FD_ISSET(ufds[i].fd, &fds_read)) {
  341. if(ufds[i].events & POLLRDNORM)
  342. ufds[i].revents |= POLLRDNORM;
  343. if(ufds[i].events & POLLIN)
  344. ufds[i].revents |= POLLIN;
  345. }
  346. if(FD_ISSET(ufds[i].fd, &fds_write)) {
  347. if(ufds[i].events & POLLWRNORM)
  348. ufds[i].revents |= POLLWRNORM;
  349. if(ufds[i].events & POLLOUT)
  350. ufds[i].revents |= POLLOUT;
  351. }
  352. if(FD_ISSET(ufds[i].fd, &fds_err)) {
  353. if(ufds[i].events & POLLRDBAND)
  354. ufds[i].revents |= POLLRDBAND;
  355. if(ufds[i].events & POLLPRI)
  356. ufds[i].revents |= POLLPRI;
  357. }
  358. if(ufds[i].revents)
  359. r++;
  360. }
  361. #endif /* HAVE_POLL */
  362. return r;
  363. }
  364. void Curl_pollfds_init(struct curl_pollfds *cpfds,
  365. struct pollfd *static_pfds,
  366. unsigned int static_count)
  367. {
  368. DEBUGASSERT(cpfds);
  369. memset(cpfds, 0, sizeof(*cpfds));
  370. if(static_pfds && static_count) {
  371. cpfds->pfds = static_pfds;
  372. cpfds->count = static_count;
  373. }
  374. }
  375. void Curl_pollfds_cleanup(struct curl_pollfds *cpfds)
  376. {
  377. DEBUGASSERT(cpfds);
  378. if(cpfds->allocated_pfds) {
  379. free(cpfds->pfds);
  380. }
  381. memset(cpfds, 0, sizeof(*cpfds));
  382. }
  383. static CURLcode cpfds_increase(struct curl_pollfds *cpfds, unsigned int inc)
  384. {
  385. struct pollfd *new_fds;
  386. unsigned int new_count = cpfds->count + inc;
  387. new_fds = calloc(new_count, sizeof(struct pollfd));
  388. if(!new_fds)
  389. return CURLE_OUT_OF_MEMORY;
  390. memcpy(new_fds, cpfds->pfds, cpfds->count * sizeof(struct pollfd));
  391. if(cpfds->allocated_pfds)
  392. free(cpfds->pfds);
  393. cpfds->pfds = new_fds;
  394. cpfds->count = new_count;
  395. cpfds->allocated_pfds = TRUE;
  396. return CURLE_OK;
  397. }
  398. static CURLcode cpfds_add_sock(struct curl_pollfds *cpfds,
  399. curl_socket_t sock, short events, bool fold)
  400. {
  401. int i;
  402. if(fold && cpfds->n <= INT_MAX) {
  403. for(i = (int)cpfds->n - 1; i >= 0; --i) {
  404. if(sock == cpfds->pfds[i].fd) {
  405. cpfds->pfds[i].events |= events;
  406. return CURLE_OK;
  407. }
  408. }
  409. }
  410. /* not folded, add new entry */
  411. if(cpfds->n >= cpfds->count) {
  412. if(cpfds_increase(cpfds, 100))
  413. return CURLE_OUT_OF_MEMORY;
  414. }
  415. cpfds->pfds[cpfds->n].fd = sock;
  416. cpfds->pfds[cpfds->n].events = events;
  417. ++cpfds->n;
  418. return CURLE_OK;
  419. }
  420. CURLcode Curl_pollfds_add_sock(struct curl_pollfds *cpfds,
  421. curl_socket_t sock, short events)
  422. {
  423. return cpfds_add_sock(cpfds, sock, events, FALSE);
  424. }
  425. CURLcode Curl_pollfds_add_ps(struct curl_pollfds *cpfds,
  426. struct easy_pollset *ps)
  427. {
  428. size_t i;
  429. DEBUGASSERT(cpfds);
  430. DEBUGASSERT(ps);
  431. for(i = 0; i < ps->num; i++) {
  432. short events = 0;
  433. if(ps->actions[i] & CURL_POLL_IN)
  434. events |= POLLIN;
  435. if(ps->actions[i] & CURL_POLL_OUT)
  436. events |= POLLOUT;
  437. if(events) {
  438. if(cpfds_add_sock(cpfds, ps->sockets[i], events, TRUE))
  439. return CURLE_OUT_OF_MEMORY;
  440. }
  441. }
  442. return CURLE_OK;
  443. }
  444. void Curl_waitfds_init(struct curl_waitfds *cwfds,
  445. struct curl_waitfd *static_wfds,
  446. unsigned int static_count)
  447. {
  448. DEBUGASSERT(cwfds);
  449. DEBUGASSERT(static_wfds);
  450. memset(cwfds, 0, sizeof(*cwfds));
  451. cwfds->wfds = static_wfds;
  452. cwfds->count = static_count;
  453. }
  454. static CURLcode cwfds_add_sock(struct curl_waitfds *cwfds,
  455. curl_socket_t sock, short events)
  456. {
  457. int i;
  458. if(cwfds->n <= INT_MAX) {
  459. for(i = (int)cwfds->n - 1; i >= 0; --i) {
  460. if(sock == cwfds->wfds[i].fd) {
  461. cwfds->wfds[i].events |= events;
  462. return CURLE_OK;
  463. }
  464. }
  465. }
  466. /* not folded, add new entry */
  467. if(cwfds->n >= cwfds->count)
  468. return CURLE_OUT_OF_MEMORY;
  469. cwfds->wfds[cwfds->n].fd = sock;
  470. cwfds->wfds[cwfds->n].events = events;
  471. ++cwfds->n;
  472. return CURLE_OK;
  473. }
  474. CURLcode Curl_waitfds_add_ps(struct curl_waitfds *cwfds,
  475. struct easy_pollset *ps)
  476. {
  477. size_t i;
  478. DEBUGASSERT(cwfds);
  479. DEBUGASSERT(ps);
  480. for(i = 0; i < ps->num; i++) {
  481. short events = 0;
  482. if(ps->actions[i] & CURL_POLL_IN)
  483. events |= CURL_WAIT_POLLIN;
  484. if(ps->actions[i] & CURL_POLL_OUT)
  485. events |= CURL_WAIT_POLLOUT;
  486. if(events) {
  487. if(cwfds_add_sock(cwfds, ps->sockets[i], events))
  488. return CURLE_OUT_OF_MEMORY;
  489. }
  490. }
  491. return CURLE_OK;
  492. }