select.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2008, 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 http://curl.haxx.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. * $Id$
  22. ***************************************************************************/
  23. #include "setup.h"
  24. #ifdef HAVE_SYS_SELECT_H
  25. #include <sys/select.h>
  26. #endif
  27. #ifdef HAVE_SYS_TIME_H
  28. #include <sys/time.h>
  29. #endif
  30. #if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
  31. #error "We can't compile without select() or poll() support."
  32. #endif
  33. #if defined(__BEOS__) && !defined(__HAIKU__)
  34. /* BeOS has FD_SET defined in socket.h */
  35. #include <socket.h>
  36. #endif
  37. #ifdef MSDOS
  38. #include <dos.h> /* delay() */
  39. #endif
  40. #include <curl/curl.h>
  41. #include "urldata.h"
  42. #include "connect.h"
  43. #include "select.h"
  44. /* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
  45. #if defined(USE_WINSOCK) || defined(TPF)
  46. #define VERIFY_SOCK(x) do { } while(0)
  47. #else
  48. #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
  49. #define VERIFY_SOCK(x) do { \
  50. if(!VALID_SOCK(x)) { \
  51. SET_SOCKERRNO(EINVAL); \
  52. return -1; \
  53. } \
  54. } while(0)
  55. #endif
  56. /* Convenience local macros */
  57. #define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
  58. #ifdef CURL_ACKNOWLEDGE_EINTR
  59. #define error_not_EINTR (1)
  60. #else
  61. #define error_not_EINTR (error != EINTR)
  62. #endif
  63. /*
  64. * Internal function used for waiting a specific amount of ms
  65. * in Curl_socket_ready() and Curl_poll() when no file descriptor
  66. * is provided to wait on, just being used to delay execution.
  67. * WinSock select() and poll() timeout mechanisms need a valid
  68. * socket descriptor in a not null file descriptor set to work.
  69. * Waiting indefinitely with this function is not allowed, a
  70. * zero or negative timeout value will return immediately.
  71. * Timeout resolution, accuracy, as well as maximum supported
  72. * value is system dependant, neither factor is a citical issue
  73. * for the intended use of this function in the library.
  74. * On non-DOS and non-Winsock platforms, when compiled with
  75. * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored
  76. * and function might exit early without awaiting full timeout,
  77. * otherwise EINTR will be ignored and full timeout will elapse.
  78. *
  79. * Return values:
  80. * -1 = system call error, invalid timeout value, or interrupted
  81. * 0 = specified timeout has elapsed
  82. */
  83. static int wait_ms(int timeout_ms)
  84. {
  85. #if !defined(MSDOS) && !defined(USE_WINSOCK)
  86. #ifndef HAVE_POLL_FINE
  87. struct timeval pending_tv;
  88. #endif
  89. struct timeval initial_tv;
  90. int pending_ms;
  91. int error;
  92. #endif
  93. int r = 0;
  94. if(!timeout_ms)
  95. return 0;
  96. if(timeout_ms < 0) {
  97. SET_SOCKERRNO(EINVAL);
  98. return -1;
  99. }
  100. #if defined(MSDOS)
  101. delay(timeout_ms);
  102. #elif defined(USE_WINSOCK)
  103. Sleep(timeout_ms);
  104. #else
  105. pending_ms = timeout_ms;
  106. initial_tv = curlx_tvnow();
  107. do {
  108. #if defined(HAVE_POLL_FINE)
  109. r = poll(NULL, 0, pending_ms);
  110. #else
  111. pending_tv.tv_sec = pending_ms / 1000;
  112. pending_tv.tv_usec = (pending_ms % 1000) * 1000;
  113. r = select(0, NULL, NULL, NULL, &pending_tv);
  114. #endif /* HAVE_POLL_FINE */
  115. if(r != -1)
  116. break;
  117. error = SOCKERRNO;
  118. if(error && error_not_EINTR)
  119. break;
  120. pending_ms = timeout_ms - elapsed_ms;
  121. if(pending_ms <= 0)
  122. break;
  123. } while(r == -1);
  124. #endif /* USE_WINSOCK */
  125. if(r)
  126. r = -1;
  127. return r;
  128. }
  129. /*
  130. * This is an internal function used for waiting for read or write
  131. * events on a pair of file descriptors. It uses poll() when a fine
  132. * poll() is available, in order to avoid limits with FD_SETSIZE,
  133. * otherwise select() is used. An error is returned if select() is
  134. * being used and a file descriptor is too large for FD_SETSIZE.
  135. * A negative timeout value makes this function wait indefinitely,
  136. * unles no valid file descriptor is given, when this happens the
  137. * negative timeout is ignored and the function times out immediately.
  138. * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
  139. * is honored and function might exit early without awaiting timeout,
  140. * otherwise EINTR will be ignored.
  141. *
  142. * Return values:
  143. * -1 = system call error or fd >= FD_SETSIZE
  144. * 0 = timeout
  145. * CURL_CSELECT_IN | CURL_CSELECT_OUT | CURL_CSELECT_ERR
  146. */
  147. int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd,
  148. int timeout_ms)
  149. {
  150. #ifdef HAVE_POLL_FINE
  151. struct pollfd pfd[2];
  152. int num;
  153. #else
  154. struct timeval pending_tv;
  155. struct timeval *ptimeout;
  156. fd_set fds_read;
  157. fd_set fds_write;
  158. fd_set fds_err;
  159. curl_socket_t maxfd;
  160. #endif
  161. struct timeval initial_tv = {0,0};
  162. int pending_ms = 0;
  163. int error;
  164. int r;
  165. int ret;
  166. if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
  167. r = wait_ms(timeout_ms);
  168. return r;
  169. }
  170. /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
  171. time in this function does not need to be measured. This happens
  172. when function is called with a zero timeout or a negative timeout
  173. value indicating a blocking call should be performed. */
  174. if(timeout_ms > 0) {
  175. pending_ms = timeout_ms;
  176. initial_tv = curlx_tvnow();
  177. }
  178. #ifdef HAVE_POLL_FINE
  179. num = 0;
  180. if(readfd != CURL_SOCKET_BAD) {
  181. pfd[num].fd = readfd;
  182. pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
  183. pfd[num].revents = 0;
  184. num++;
  185. }
  186. if(writefd != CURL_SOCKET_BAD) {
  187. pfd[num].fd = writefd;
  188. pfd[num].events = POLLWRNORM|POLLOUT;
  189. pfd[num].revents = 0;
  190. num++;
  191. }
  192. do {
  193. if(timeout_ms < 0)
  194. pending_ms = -1;
  195. else if(!timeout_ms)
  196. pending_ms = 0;
  197. r = poll(pfd, num, pending_ms);
  198. if(r != -1)
  199. break;
  200. error = SOCKERRNO;
  201. if(error && error_not_EINTR)
  202. break;
  203. if(timeout_ms > 0) {
  204. pending_ms = timeout_ms - elapsed_ms;
  205. if(pending_ms <= 0)
  206. break;
  207. }
  208. } while(r == -1);
  209. if(r < 0)
  210. return -1;
  211. if(r == 0)
  212. return 0;
  213. ret = 0;
  214. num = 0;
  215. if(readfd != CURL_SOCKET_BAD) {
  216. if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
  217. ret |= CURL_CSELECT_IN;
  218. if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
  219. ret |= CURL_CSELECT_ERR;
  220. num++;
  221. }
  222. if(writefd != CURL_SOCKET_BAD) {
  223. if(pfd[num].revents & (POLLWRNORM|POLLOUT))
  224. ret |= CURL_CSELECT_OUT;
  225. if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
  226. ret |= CURL_CSELECT_ERR;
  227. }
  228. return ret;
  229. #else /* HAVE_POLL_FINE */
  230. FD_ZERO(&fds_err);
  231. maxfd = (curl_socket_t)-1;
  232. FD_ZERO(&fds_read);
  233. if(readfd != CURL_SOCKET_BAD) {
  234. VERIFY_SOCK(readfd);
  235. FD_SET(readfd, &fds_read);
  236. FD_SET(readfd, &fds_err);
  237. maxfd = readfd;
  238. }
  239. FD_ZERO(&fds_write);
  240. if(writefd != CURL_SOCKET_BAD) {
  241. VERIFY_SOCK(writefd);
  242. FD_SET(writefd, &fds_write);
  243. FD_SET(writefd, &fds_err);
  244. if(writefd > maxfd)
  245. maxfd = writefd;
  246. }
  247. ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
  248. do {
  249. if(timeout_ms > 0) {
  250. pending_tv.tv_sec = pending_ms / 1000;
  251. pending_tv.tv_usec = (pending_ms % 1000) * 1000;
  252. }
  253. else if(!timeout_ms) {
  254. pending_tv.tv_sec = 0;
  255. pending_tv.tv_usec = 0;
  256. }
  257. r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
  258. if(r != -1)
  259. break;
  260. error = SOCKERRNO;
  261. if(error && error_not_EINTR)
  262. break;
  263. if(timeout_ms > 0) {
  264. pending_ms = timeout_ms - elapsed_ms;
  265. if(pending_ms <= 0)
  266. break;
  267. }
  268. } while(r == -1);
  269. if(r < 0)
  270. return -1;
  271. if(r == 0)
  272. return 0;
  273. ret = 0;
  274. if(readfd != CURL_SOCKET_BAD) {
  275. if(FD_ISSET(readfd, &fds_read))
  276. ret |= CURL_CSELECT_IN;
  277. if(FD_ISSET(readfd, &fds_err))
  278. ret |= CURL_CSELECT_ERR;
  279. }
  280. if(writefd != CURL_SOCKET_BAD) {
  281. if(FD_ISSET(writefd, &fds_write))
  282. ret |= CURL_CSELECT_OUT;
  283. if(FD_ISSET(writefd, &fds_err))
  284. ret |= CURL_CSELECT_ERR;
  285. }
  286. return ret;
  287. #endif /* HAVE_POLL_FINE */
  288. }
  289. /*
  290. * This is a wrapper around poll(). If poll() does not exist, then
  291. * select() is used instead. An error is returned if select() is
  292. * being used and a file descriptor is too large for FD_SETSIZE.
  293. * A negative timeout value makes this function wait indefinitely,
  294. * unles no valid file descriptor is given, when this happens the
  295. * negative timeout is ignored and the function times out immediately.
  296. * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
  297. * is honored and function might exit early without awaiting timeout,
  298. * otherwise EINTR will be ignored.
  299. *
  300. * Return values:
  301. * -1 = system call error or fd >= FD_SETSIZE
  302. * 0 = timeout
  303. * N = number of structures with non zero revent fields
  304. */
  305. int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
  306. {
  307. #ifndef HAVE_POLL_FINE
  308. struct timeval pending_tv;
  309. struct timeval *ptimeout;
  310. fd_set fds_read;
  311. fd_set fds_write;
  312. fd_set fds_err;
  313. curl_socket_t maxfd;
  314. #endif
  315. struct timeval initial_tv = {0,0};
  316. bool fds_none = TRUE;
  317. unsigned int i;
  318. int pending_ms = 0;
  319. int error;
  320. int r;
  321. if(ufds) {
  322. for (i = 0; i < nfds; i++) {
  323. if(ufds[i].fd != CURL_SOCKET_BAD) {
  324. fds_none = FALSE;
  325. break;
  326. }
  327. }
  328. }
  329. if(fds_none) {
  330. r = wait_ms(timeout_ms);
  331. return r;
  332. }
  333. /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
  334. time in this function does not need to be measured. This happens
  335. when function is called with a zero timeout or a negative timeout
  336. value indicating a blocking call should be performed. */
  337. if(timeout_ms > 0) {
  338. pending_ms = timeout_ms;
  339. initial_tv = curlx_tvnow();
  340. }
  341. #ifdef HAVE_POLL_FINE
  342. do {
  343. if(timeout_ms < 0)
  344. pending_ms = -1;
  345. else if(!timeout_ms)
  346. pending_ms = 0;
  347. r = poll(ufds, nfds, pending_ms);
  348. if(r != -1)
  349. break;
  350. error = SOCKERRNO;
  351. if(error && error_not_EINTR)
  352. break;
  353. if(timeout_ms > 0) {
  354. pending_ms = timeout_ms - elapsed_ms;
  355. if(pending_ms <= 0)
  356. break;
  357. }
  358. } while(r == -1);
  359. #else /* HAVE_POLL_FINE */
  360. FD_ZERO(&fds_read);
  361. FD_ZERO(&fds_write);
  362. FD_ZERO(&fds_err);
  363. maxfd = (curl_socket_t)-1;
  364. for (i = 0; i < nfds; i++) {
  365. ufds[i].revents = 0;
  366. if(ufds[i].fd == CURL_SOCKET_BAD)
  367. continue;
  368. VERIFY_SOCK(ufds[i].fd);
  369. if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
  370. POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
  371. if(ufds[i].fd > maxfd)
  372. maxfd = ufds[i].fd;
  373. if(ufds[i].events & (POLLRDNORM|POLLIN))
  374. FD_SET(ufds[i].fd, &fds_read);
  375. if(ufds[i].events & (POLLWRNORM|POLLOUT))
  376. FD_SET(ufds[i].fd, &fds_write);
  377. if(ufds[i].events & (POLLRDBAND|POLLPRI))
  378. FD_SET(ufds[i].fd, &fds_err);
  379. }
  380. }
  381. ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
  382. do {
  383. if(timeout_ms > 0) {
  384. pending_tv.tv_sec = pending_ms / 1000;
  385. pending_tv.tv_usec = (pending_ms % 1000) * 1000;
  386. }
  387. else if(!timeout_ms) {
  388. pending_tv.tv_sec = 0;
  389. pending_tv.tv_usec = 0;
  390. }
  391. r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
  392. if(r != -1)
  393. break;
  394. error = SOCKERRNO;
  395. if(error && error_not_EINTR)
  396. break;
  397. if(timeout_ms > 0) {
  398. pending_ms = timeout_ms - elapsed_ms;
  399. if(pending_ms <= 0)
  400. break;
  401. }
  402. } while(r == -1);
  403. if(r < 0)
  404. return -1;
  405. if(r == 0)
  406. return 0;
  407. r = 0;
  408. for (i = 0; i < nfds; i++) {
  409. ufds[i].revents = 0;
  410. if(ufds[i].fd == CURL_SOCKET_BAD)
  411. continue;
  412. if(FD_ISSET(ufds[i].fd, &fds_read))
  413. ufds[i].revents |= POLLIN;
  414. if(FD_ISSET(ufds[i].fd, &fds_write))
  415. ufds[i].revents |= POLLOUT;
  416. if(FD_ISSET(ufds[i].fd, &fds_err))
  417. ufds[i].revents |= POLLPRI;
  418. if(ufds[i].revents != 0)
  419. r++;
  420. }
  421. #endif /* HAVE_POLL_FINE */
  422. return r;
  423. }
  424. #ifdef TPF
  425. /*
  426. * This is a replacement for select() on the TPF platform.
  427. * It is used whenever libcurl calls select().
  428. * The call below to tpf_process_signals() is required because
  429. * TPF's select calls are not signal interruptible.
  430. *
  431. * Return values are the same as select's.
  432. */
  433. int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
  434. fd_set* excepts, struct timeval* tv)
  435. {
  436. int rc;
  437. rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
  438. tpf_process_signals();
  439. return(rc);
  440. }
  441. #endif /* TPF */