44
39
#include <socket.h>
43
#include <dos.h> /* delay() */
47
46
#include <curl/curl.h>
49
48
#include "urldata.h"
50
49
#include "connect.h"
51
50
#include "select.h"
53
#if defined(WIN32) || defined(TPF)
54
#define VERIFY_SOCK(x) /* sockets are not in range [0..FD_SETSIZE] */
52
/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
54
#if defined(USE_WINSOCK) || defined(TPF)
55
#define VERIFY_SOCK(x) do { } while (0)
56
#define VERIFY_NFDS(x) do { } while (0)
56
58
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
57
59
#define VERIFY_SOCK(x) do { \
58
60
if(!VALID_SOCK(x)) { \
61
SET_SOCKERRNO(EINVAL); \
65
#define VALID_NFDS(n) (((n) >= 0) && ((n) <= FD_SETSIZE))
66
#define VERIFY_NFDS(x) do { \
67
if(!VALID_NFDS(x)) { \
68
SET_SOCKERRNO(EINVAL); \
74
/* Convenience local macros */
76
#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
78
#ifdef CURL_ACKNOWLEDGE_EINTR
79
#define error_not_EINTR (error != EINTR)
81
#define error_not_EINTR (1)
84
#define SMALL_POLLNFDS 0X20
87
* Internal function used for waiting a specific amount of ms
88
* in Curl_socket_ready() and Curl_poll() when no file descriptor
89
* is provided to wait on, just being used to delay execution.
90
* WinSock select() and poll() timeout mechanisms need a valid
91
* socket descriptor in a not null file descriptor set to work.
92
* Waiting indefinitely with this function is not allowed, a
93
* zero or negative timeout value will return immediately.
94
* Timeout resolution, accuracy, as well as maximum supported
95
* value is system dependant, neither factor is a citical issue
96
* for the intended use of this function in the library.
97
* On non-DOS and non-Winsock platforms, when compiled with
98
* CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored
99
* and function might exit early without awaiting full timeout,
100
* otherwise EINTR will be ignored and full timeout will elapse.
103
* -1 = system call error, invalid timeout value, or interrupted
104
* 0 = specified timeout has elapsed
106
static int wait_ms(int timeout_ms)
108
#if !defined(MSDOS) && !defined(USE_WINSOCK)
109
#ifndef HAVE_POLL_FINE
110
struct timeval pending_tv;
112
struct timeval initial_tv;
120
if (timeout_ms < 0) {
121
SET_SOCKERRNO(EINVAL);
126
#elif defined(USE_WINSOCK)
129
pending_ms = timeout_ms;
130
initial_tv = curlx_tvnow();
132
#if defined(HAVE_POLL_FINE)
133
r = poll(NULL, 0, pending_ms);
135
pending_tv.tv_sec = pending_ms / 1000;
136
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
137
r = select(0, NULL, NULL, NULL, &pending_tv);
138
#endif /* HAVE_POLL_FINE */
139
} while ((r == -1) && (error = SOCKERRNO) &&
140
(error != EINVAL) && error_not_EINTR &&
141
((pending_ms = timeout_ms - elapsed_ms) > 0));
142
#endif /* USE_WINSOCK */
66
149
* This is an internal function used for waiting for read or write
67
* events on single file descriptors. It attempts to replace select()
68
* in order to avoid limits with FD_SETSIZE.
150
* events on a pair of file descriptors. It uses poll() when a fine
151
* poll() is available, in order to avoid limits with FD_SETSIZE,
152
* otherwise select() is used. An error is returned if select() is
153
* being used and a file descriptor is too large for FD_SETSIZE.
154
* A negative timeout value makes this function wait indefinitely,
155
* unles no valid file descriptor is given, when this happens the
156
* negative timeout is ignored and the function times out immediately.
157
* When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
158
* is honored and function might exit early without awaiting timeout,
159
* otherwise EINTR will be ignored.
71
* -1 = system call error
162
* -1 = system call error or fd >= FD_SETSIZE
73
164
* CSELECT_IN | CSELECT_OUT | CSELECT_ERR
75
int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
166
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
77
168
#ifdef HAVE_POLL_FINE
78
169
struct pollfd pfd[2];
172
struct timeval pending_tv;
173
struct timeval *ptimeout;
179
struct timeval initial_tv;
185
if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
186
r = wait_ms(timeout_ms);
190
pending_ms = timeout_ms;
191
initial_tv = curlx_tvnow();
193
#ifdef HAVE_POLL_FINE
84
196
if (readfd != CURL_SOCKET_BAD) {
85
197
pfd[num].fd = readfd;
86
pfd[num].events = POLLIN;
198
pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
199
pfd[num].revents = 0;
89
202
if (writefd != CURL_SOCKET_BAD) {
90
203
pfd[num].fd = writefd;
91
pfd[num].events = POLLOUT;
204
pfd[num].events = POLLWRNORM|POLLOUT;
205
pfd[num].revents = 0;
96
r = poll(pfd, num, timeout_ms);
97
} while((r == -1) && (errno == EINTR));
212
r = poll(pfd, num, pending_ms);
213
} while ((r == -1) && (error = SOCKERRNO) &&
214
(error != EINVAL) && error_not_EINTR &&
215
((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
295
#endif /* HAVE_POLL_FINE */
181
300
* This is a wrapper around poll(). If poll() does not exist, then
182
301
* select() is used instead. An error is returned if select() is
183
* being used and a file descriptor too large for FD_SETSIZE.
302
* being used and a file descriptor is too large for FD_SETSIZE.
303
* A negative timeout value makes this function wait indefinitely,
304
* unles no valid file descriptor is given, when this happens the
305
* negative timeout is ignored and the function times out immediately.
306
* When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
307
* is honored and function might exit early without awaiting timeout,
308
* otherwise EINTR will be ignored.
186
311
* -1 = system call error or fd >= FD_SETSIZE
188
* 1 = number of structures with non zero revent fields
313
* N = number of structures with non zero revent fields
190
315
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
193
#ifdef HAVE_POLL_FINE
195
r = poll(ufds, nfds, timeout_ms);
196
} while((r == -1) && (errno == EINTR));
198
struct timeval timeout;
317
#ifndef HAVE_POLL_FINE
318
struct timeval pending_tv;
199
319
struct timeval *ptimeout;
201
321
fd_set fds_write;
203
323
curl_socket_t maxfd;
325
struct timeval initial_tv;
326
bool fds_none = TRUE;
333
for (i = 0; i < nfds; i++) {
334
if (ufds[i].fd != CURL_SOCKET_BAD) {
341
r = wait_ms(timeout_ms);
345
pending_ms = timeout_ms;
346
initial_tv = curlx_tvnow();
348
#ifdef HAVE_POLL_FINE
353
r = poll(ufds, nfds, pending_ms);
354
} while ((r == -1) && (error = SOCKERRNO) &&
355
(error != EINVAL) && error_not_EINTR &&
356
((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
358
#else /* HAVE_POLL_FINE */
206
360
FD_ZERO(&fds_read);
207
361
FD_ZERO(&fds_write);
209
363
maxfd = (curl_socket_t)-1;
211
365
for (i = 0; i < nfds; i++) {
212
367
if (ufds[i].fd == CURL_SOCKET_BAD)
214
#ifndef WIN32 /* This is harmless and wrong on Win32 */
215
if (ufds[i].fd >= FD_SETSIZE) {
369
VERIFY_SOCK(ufds[i].fd);
370
if (ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
371
POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
372
if (ufds[i].fd > maxfd)
374
if (ufds[i].events & (POLLRDNORM|POLLIN))
375
FD_SET(ufds[i].fd, &fds_read);
376
if (ufds[i].events & (POLLWRNORM|POLLOUT))
377
FD_SET(ufds[i].fd, &fds_write);
378
if (ufds[i].events & (POLLRDBAND|POLLPRI))
379
FD_SET(ufds[i].fd, &fds_err);
220
if (ufds[i].fd > maxfd)
222
if (ufds[i].events & POLLIN)
223
FD_SET(ufds[i].fd, &fds_read);
224
if (ufds[i].events & POLLOUT)
225
FD_SET(ufds[i].fd, &fds_write);
226
if (ufds[i].events & POLLERR)
227
FD_SET(ufds[i].fd, &fds_err);
230
if (timeout_ms < 0) {
231
ptimeout = NULL; /* wait forever */
233
timeout.tv_sec = timeout_ms / 1000;
234
timeout.tv_usec = (timeout_ms % 1000) * 1000;
383
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
387
pending_tv.tv_sec = pending_ms / 1000;
388
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
239
390
r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
240
} while((r == -1) && (Curl_sockerrno() == EINTR));
391
} while ((r == -1) && (error = SOCKERRNO) &&
392
(error != EINVAL) && (error != EBADF) && error_not_EINTR &&
393
((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
254
407
if (FD_ISSET(ufds[i].fd, &fds_write))
255
408
ufds[i].revents |= POLLOUT;
256
409
if (FD_ISSET(ufds[i].fd, &fds_err))
257
ufds[i].revents |= POLLERR;
410
ufds[i].revents |= POLLPRI;
258
411
if (ufds[i].revents != 0)
415
#endif /* HAVE_POLL_FINE */
421
* This is a wrapper around select(). It uses poll() when a fine
422
* poll() is available, in order to avoid limits with FD_SETSIZE,
423
* otherwise select() is used. An error is returned if select() is
424
* being used and a the number of file descriptors is larger than
425
* FD_SETSIZE. A NULL timeout pointer makes this function wait
426
* indefinitely, unles no valid file descriptor is given, when this
427
* happens the NULL timeout is ignored and the function times out
428
* immediately. When compiled with CURL_ACKNOWLEDGE_EINTR defined,
429
* EINTR condition is honored and function might exit early without
430
* awaiting timeout, otherwise EINTR will be ignored.
433
* -1 = system call error or nfds > FD_SETSIZE
435
* N = number of file descriptors kept in file descriptor sets.
437
int Curl_select(int nfds,
438
fd_set *fds_read, fd_set *fds_write, fd_set *fds_excep,
439
struct timeval *timeout)
441
struct timeval initial_tv;
446
#ifdef HAVE_POLL_FINE
447
struct pollfd small_fds[SMALL_POLLNFDS];
448
struct pollfd *poll_fds;
453
struct timeval pending_tv;
454
struct timeval *ptimeout;
459
((nfds > 0) && (!fds_read && !fds_write && !fds_excep))) {
460
SET_SOCKERRNO(EINVAL);
465
if ((timeout->tv_sec < 0) ||
466
(timeout->tv_usec < 0) ||
467
(timeout->tv_usec >= 1000000)) {
468
SET_SOCKERRNO(EINVAL);
471
timeout_ms = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
477
if ((!nfds) || (!fds_read && !fds_write && !fds_excep)) {
478
r = wait_ms(timeout_ms);
482
pending_ms = timeout_ms;
483
initial_tv = curlx_tvnow();
485
#ifdef HAVE_POLL_FINE
487
if (fds_read || fds_write || fds_excep) {
490
if ((fds_read && (0 != FD_ISSET(fd, fds_read))) ||
491
(fds_write && (0 != FD_ISSET(fd, fds_write))) ||
492
(fds_excep && (0 != FD_ISSET(fd, fds_excep))))
499
else if (poll_nfds <= SMALL_POLLNFDS)
500
poll_fds = small_fds;
502
poll_fds = calloc((size_t)poll_nfds, sizeof(struct pollfd));
504
SET_SOCKERRNO(ENOBUFS);
513
poll_fds[ix].events = 0;
514
if (fds_read && (0 != FD_ISSET(fd, fds_read)))
515
poll_fds[ix].events |= (POLLRDNORM|POLLIN);
516
if (fds_write && (0 != FD_ISSET(fd, fds_write)))
517
poll_fds[ix].events |= (POLLWRNORM|POLLOUT);
518
if (fds_excep && (0 != FD_ISSET(fd, fds_excep)))
519
poll_fds[ix].events |= (POLLRDBAND|POLLPRI);
520
if (poll_fds[ix].events) {
521
poll_fds[ix].fd = fd;
522
poll_fds[ix].revents = 0;
531
r = poll(poll_fds, poll_nfds, pending_ms);
532
} while ((r == -1) && (error = SOCKERRNO) &&
533
(error != EINVAL) && error_not_EINTR &&
534
((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
542
if (poll_fds[ix].revents & POLLNVAL) {
543
SET_SOCKERRNO(EBADF);
553
if (fds_read && (0 != FD_ISSET(poll_fds[ix].fd, fds_read))) {
554
if (0 == (poll_fds[ix].revents & (POLLRDNORM|POLLERR|POLLHUP|POLLIN)))
555
FD_CLR(poll_fds[ix].fd, fds_read);
559
if (fds_write && (0 != FD_ISSET(poll_fds[ix].fd, fds_write))) {
560
if (0 == (poll_fds[ix].revents & (POLLWRNORM|POLLERR|POLLHUP|POLLOUT)))
561
FD_CLR(poll_fds[ix].fd, fds_write);
565
if (fds_excep && (0 != FD_ISSET(poll_fds[ix].fd, fds_excep))) {
566
if (0 == (poll_fds[ix].revents & (POLLRDBAND|POLLERR|POLLHUP|POLLPRI)))
567
FD_CLR(poll_fds[ix].fd, fds_excep);
574
if (poll_fds && (poll_nfds > SMALL_POLLNFDS))
577
#else /* HAVE_POLL_FINE */
581
ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
585
pending_tv.tv_sec = pending_ms / 1000;
586
pending_tv.tv_usec = (pending_ms % 1000) * 1000;
588
r = select(nfds, fds_read, fds_write, fds_excep, ptimeout);
589
} while ((r == -1) && (error = SOCKERRNO) &&
590
(error != EINVAL) && (error != EBADF) && error_not_EINTR &&
591
((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
598
#endif /* HAVE_POLL_FINE */