2
0

select.c 16 KB

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