Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl / select.c
blob1db4407e8c095ce51b20dcf68fc7ed2a6069e849
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
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.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 <<<<<<< select.c
22 * $Id: select.c,v 1.2 2007/03/15 19:22:13 andy Exp $
23 =======
24 * $Id: select.c,v 1.3 2008-09-15 22:23:37 hoffman Exp $
25 >>>>>>> 1.3
26 ***************************************************************************/
28 #include "setup.h"
30 #include <errno.h>
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
35 #ifdef HAVE_SYS_SELECT_H
36 #include <sys/select.h>
37 #endif
38 #ifdef HAVE_SYS_TIME_H
39 #include <sys/time.h>
40 #endif
42 #ifndef HAVE_SELECT
43 #error "We can't compile without select() support!"
44 #endif
46 #if defined(__BEOS__) && !defined(__HAIKU__)
47 /* BeOS has FD_SET defined in socket.h */
48 #include <socket.h>
49 #endif
51 #ifdef __MSDOS__
52 #include <dos.h> /* delay() */
53 #endif
55 #include <curl/curl.h>
57 #include "urldata.h"
58 #include "connect.h"
59 #include "select.h"
61 #if defined(USE_WINSOCK) || defined(TPF)
62 #define VERIFY_SOCK(x) /* sockets are not in range [0..FD_SETSIZE] */
63 #else
64 #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
65 #define VERIFY_SOCK(x) do { \
66 if(!VALID_SOCK(x)) { \
67 errno = EINVAL; \
68 return -1; \
69 } \
70 } while(0)
71 #endif
74 * This is an internal function used for waiting for read or write
75 * events on single file descriptors. It attempts to replace select()
76 * in order to avoid limits with FD_SETSIZE.
78 * Return values:
79 * -1 = system call error
80 * 0 = timeout
81 * CSELECT_IN | CSELECT_OUT | CSELECT_ERR
83 int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
85 #if defined(HAVE_POLL_FINE) || defined(CURL_HAVE_WSAPOLL)
86 struct pollfd pfd[2];
87 int num;
88 int r;
89 int ret;
91 num = 0;
92 if (readfd != CURL_SOCKET_BAD) {
93 pfd[num].fd = readfd;
94 pfd[num].events = POLLIN;
95 num++;
97 if (writefd != CURL_SOCKET_BAD) {
98 pfd[num].fd = writefd;
99 pfd[num].events = POLLOUT;
100 num++;
103 #ifdef HAVE_POLL_FINE
104 do {
105 r = poll(pfd, num, timeout_ms);
106 } while((r == -1) && (errno == EINTR));
107 #else
108 r = WSAPoll(pfd, num, timeout_ms);
109 #endif
111 if (r < 0)
112 return -1;
113 if (r == 0)
114 return 0;
116 ret = 0;
117 num = 0;
118 if (readfd != CURL_SOCKET_BAD) {
119 if (pfd[num].revents & (POLLIN|POLLHUP))
120 ret |= CSELECT_IN;
121 if (pfd[num].revents & POLLERR) {
122 #ifdef __CYGWIN__
123 /* Cygwin 1.5.21 needs this hack to pass test 160 */
124 if (errno == EINPROGRESS)
125 ret |= CSELECT_IN;
126 else
127 #endif
128 ret |= CSELECT_ERR;
130 num++;
132 if (writefd != CURL_SOCKET_BAD) {
133 if (pfd[num].revents & POLLOUT)
134 ret |= CSELECT_OUT;
135 if (pfd[num].revents & (POLLERR|POLLHUP))
136 ret |= CSELECT_ERR;
139 return ret;
140 #else
141 struct timeval timeout;
142 fd_set fds_read;
143 fd_set fds_write;
144 fd_set fds_err;
145 curl_socket_t maxfd;
146 int r;
147 int ret;
149 timeout.tv_sec = timeout_ms / 1000;
150 timeout.tv_usec = (timeout_ms % 1000) * 1000;
152 if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
153 /* According to POSIX we should pass in NULL pointers if we don't want to
154 wait for anything in particular but just use the timeout function.
155 Windows however returns immediately if done so. I copied the MSDOS
156 delay() use from src/main.c that already had this work-around. */
157 #ifdef WIN32
158 Sleep(timeout_ms);
159 #elif defined(__MSDOS__)
160 delay(timeout_ms);
161 #else
162 select(0, NULL, NULL, NULL, &timeout);
163 #endif
164 return 0;
167 FD_ZERO(&fds_err);
168 maxfd = (curl_socket_t)-1;
170 FD_ZERO(&fds_read);
171 if (readfd != CURL_SOCKET_BAD) {
172 VERIFY_SOCK(readfd);
173 FD_SET(readfd, &fds_read);
174 FD_SET(readfd, &fds_err);
175 maxfd = readfd;
178 FD_ZERO(&fds_write);
179 if (writefd != CURL_SOCKET_BAD) {
180 VERIFY_SOCK(writefd);
181 FD_SET(writefd, &fds_write);
182 FD_SET(writefd, &fds_err);
183 if (writefd > maxfd)
184 maxfd = writefd;
187 do {
188 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
189 } while((r == -1) && (Curl_sockerrno() == EINTR));
191 if (r < 0)
192 return -1;
193 if (r == 0)
194 return 0;
196 ret = 0;
197 if (readfd != CURL_SOCKET_BAD) {
198 if (FD_ISSET(readfd, &fds_read))
199 ret |= CSELECT_IN;
200 if (FD_ISSET(readfd, &fds_err))
201 ret |= CSELECT_ERR;
203 if (writefd != CURL_SOCKET_BAD) {
204 if (FD_ISSET(writefd, &fds_write))
205 ret |= CSELECT_OUT;
206 if (FD_ISSET(writefd, &fds_err))
207 ret |= CSELECT_ERR;
210 return ret;
211 #endif
215 * This is a wrapper around poll(). If poll() does not exist, then
216 * select() is used instead. An error is returned if select() is
217 * being used and a file descriptor too large for FD_SETSIZE.
219 * Return values:
220 * -1 = system call error or fd >= FD_SETSIZE
221 * 0 = timeout
222 * 1 = number of structures with non zero revent fields
224 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
226 int r;
227 #ifdef HAVE_POLL_FINE
228 do {
229 r = poll(ufds, nfds, timeout_ms);
230 } while((r == -1) && (errno == EINTR));
231 #elif defined(CURL_HAVE_WSAPOLL)
232 r = WSAPoll(ufds, nfds, timeout_ms);
233 #else
234 struct timeval timeout;
235 struct timeval *ptimeout;
236 fd_set fds_read;
237 fd_set fds_write;
238 fd_set fds_err;
239 curl_socket_t maxfd;
240 unsigned int i;
242 FD_ZERO(&fds_read);
243 FD_ZERO(&fds_write);
244 FD_ZERO(&fds_err);
245 maxfd = (curl_socket_t)-1;
247 for (i = 0; i < nfds; i++) {
248 if (ufds[i].fd == CURL_SOCKET_BAD)
249 continue;
250 #ifndef USE_WINSOCK /* winsock sockets are not in range [0..FD_SETSIZE] */
251 if (ufds[i].fd >= FD_SETSIZE) {
252 errno = EINVAL;
253 return -1;
255 #endif
256 if (ufds[i].fd > maxfd)
257 maxfd = ufds[i].fd;
258 if (ufds[i].events & POLLIN)
259 FD_SET(ufds[i].fd, &fds_read);
260 if (ufds[i].events & POLLOUT)
261 FD_SET(ufds[i].fd, &fds_write);
262 if (ufds[i].events & POLLERR)
263 FD_SET(ufds[i].fd, &fds_err);
266 if (timeout_ms < 0) {
267 ptimeout = NULL; /* wait forever */
268 } else {
269 timeout.tv_sec = timeout_ms / 1000;
270 timeout.tv_usec = (timeout_ms % 1000) * 1000;
271 ptimeout = &timeout;
274 do {
275 r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
276 } while((r == -1) && (Curl_sockerrno() == EINTR));
278 if (r < 0)
279 return -1;
280 if (r == 0)
281 return 0;
283 r = 0;
284 for (i = 0; i < nfds; i++) {
285 ufds[i].revents = 0;
286 if (ufds[i].fd == CURL_SOCKET_BAD)
287 continue;
288 if (FD_ISSET(ufds[i].fd, &fds_read))
289 ufds[i].revents |= POLLIN;
290 if (FD_ISSET(ufds[i].fd, &fds_write))
291 ufds[i].revents |= POLLOUT;
292 if (FD_ISSET(ufds[i].fd, &fds_err))
293 ufds[i].revents |= POLLERR;
294 if (ufds[i].revents != 0)
295 r++;
297 #endif
298 return r;
301 #ifdef TPF
303 * This is a replacement for select() on the TPF platform.
304 * It is used whenever libcurl calls select().
305 * The call below to tpf_process_signals() is required because
306 * TPF's select calls are not signal interruptible.
308 * Return values are the same as select's.
310 int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
311 fd_set* excepts, struct timeval* tv)
313 int rc;
315 rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
316 tpf_process_signals();
317 return(rc);
319 #endif /* TPF */