Export new ABIs. Doc fixes for new APIs.
[gnutls.git] / gl / select.c
blob0c0e3eefc981169d2d1d5b5710caf8b6ec16980f
1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2010 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22 #include <config.h>
23 #include <alloca.h>
24 #include <assert.h>
26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
27 /* Native Win32. */
29 #include <sys/types.h>
30 #include <stdbool.h>
31 #include <errno.h>
32 #include <limits.h>
34 #include <winsock2.h>
35 #include <windows.h>
36 #include <io.h>
37 #include <stdio.h>
38 #include <conio.h>
39 #include <time.h>
41 struct bitset {
42 unsigned char in[FD_SETSIZE / CHAR_BIT];
43 unsigned char out[FD_SETSIZE / CHAR_BIT];
46 /* Declare data structures for ntdll functions. */
47 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
48 ULONG NamedPipeType;
49 ULONG NamedPipeConfiguration;
50 ULONG MaximumInstances;
51 ULONG CurrentInstances;
52 ULONG InboundQuota;
53 ULONG ReadDataAvailable;
54 ULONG OutboundQuota;
55 ULONG WriteQuotaAvailable;
56 ULONG NamedPipeState;
57 ULONG NamedPipeEnd;
58 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
60 typedef struct _IO_STATUS_BLOCK
62 union {
63 DWORD Status;
64 PVOID Pointer;
65 } u;
66 ULONG_PTR Information;
67 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
69 typedef enum _FILE_INFORMATION_CLASS {
70 FilePipeLocalInformation = 24
71 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
73 typedef DWORD (WINAPI *PNtQueryInformationFile)
74 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
76 #ifndef PIPE_BUF
77 #define PIPE_BUF 512
78 #endif
80 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
82 static BOOL
83 IsSocketHandle (HANDLE h)
85 WSANETWORKEVENTS ev;
87 if (IsConsoleHandle (h))
88 return FALSE;
90 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
91 WSAEnumNetworkEvents instead distinguishes the two correctly. */
92 ev.lNetworkEvents = 0xDEADBEEF;
93 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
94 return ev.lNetworkEvents != 0xDEADBEEF;
97 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
99 static int
100 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
101 struct bitset *xbits)
103 BOOL read, write, except;
104 int i, ret;
105 INPUT_RECORD *irbuffer;
106 DWORD avail, nbuffer;
107 BOOL bRet;
108 IO_STATUS_BLOCK iosb;
109 FILE_PIPE_LOCAL_INFORMATION fpli;
110 static PNtQueryInformationFile NtQueryInformationFile;
111 static BOOL once_only;
113 read = write = except = FALSE;
114 switch (GetFileType (h))
116 case FILE_TYPE_DISK:
117 read = TRUE;
118 write = TRUE;
119 break;
121 case FILE_TYPE_PIPE:
122 if (!once_only)
124 NtQueryInformationFile = (PNtQueryInformationFile)
125 GetProcAddress (GetModuleHandle ("ntdll.dll"),
126 "NtQueryInformationFile");
127 once_only = TRUE;
130 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
132 if (avail)
133 read = TRUE;
136 else
138 /* It was the write-end of the pipe. Check if it is writable.
139 If NtQueryInformationFile fails, optimistically assume the pipe is
140 writable. This could happen on Win9x, where NtQueryInformationFile
141 is not available, or if we inherit a pipe that doesn't permit
142 FILE_READ_ATTRIBUTES access on the write end (I think this should
143 not happen since WinXP SP2; WINE seems fine too). Otherwise,
144 ensure that enough space is available for atomic writes. */
145 memset (&iosb, 0, sizeof (iosb));
146 memset (&fpli, 0, sizeof (fpli));
148 if (!NtQueryInformationFile
149 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
150 FilePipeLocalInformation)
151 || fpli.WriteQuotaAvailable >= PIPE_BUF
152 || (fpli.OutboundQuota < PIPE_BUF &&
153 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
154 write = TRUE;
156 break;
158 case FILE_TYPE_CHAR:
159 write = TRUE;
160 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
161 break;
163 ret = WaitForSingleObject (h, 0);
164 if (ret == WAIT_OBJECT_0)
166 if (!IsConsoleHandle (h))
168 read = TRUE;
169 break;
172 nbuffer = avail = 0;
173 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
175 /* Screen buffers handles are filtered earlier. */
176 assert (bRet);
177 if (nbuffer == 0)
179 except = TRUE;
180 break;
183 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
184 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
185 if (!bRet || avail == 0)
187 except = TRUE;
188 break;
191 for (i = 0; i < avail; i++)
192 if (irbuffer[i].EventType == KEY_EVENT)
193 read = TRUE;
195 break;
197 default:
198 ret = WaitForSingleObject (h, 0);
199 write = TRUE;
200 if (ret == WAIT_OBJECT_0)
201 read = TRUE;
203 break;
206 ret = 0;
207 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
209 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
210 ret++;
213 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
215 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
216 ret++;
219 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
221 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
222 ret++;
225 return ret;
229 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
230 struct timeval *timeout)
232 static struct timeval tv0;
233 static HANDLE hEvent;
234 HANDLE h, handle_array[FD_SETSIZE + 2];
235 fd_set handle_rfds, handle_wfds, handle_xfds;
236 struct bitset rbits, wbits, xbits;
237 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
238 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
239 MSG msg;
240 int i, fd, rc;
242 if (nfds > FD_SETSIZE)
243 nfds = FD_SETSIZE;
245 if (!timeout)
246 wait_timeout = INFINITE;
247 else
249 wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
251 /* select is also used as a portable usleep. */
252 if (!rfds && !wfds && !xfds)
254 Sleep (wait_timeout);
255 return 0;
259 if (!hEvent)
260 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
262 handle_array[0] = hEvent;
263 nhandles = 1;
264 nsock = 0;
266 /* Copy descriptors to bitsets. At the same time, eliminate
267 bits in the "wrong" direction for console input buffers
268 and screen buffers, because screen buffers are waitable
269 and they will block until a character is available. */
270 memset (&rbits, 0, sizeof (rbits));
271 memset (&wbits, 0, sizeof (wbits));
272 memset (&xbits, 0, sizeof (xbits));
273 memset (anyfds_in, 0, sizeof (anyfds_in));
274 if (rfds)
275 for (i = 0; i < rfds->fd_count; i++)
277 fd = rfds->fd_array[i];
278 h = (HANDLE) _get_osfhandle (fd);
279 if (IsConsoleHandle (h)
280 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
281 continue;
283 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
284 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
286 else
287 rfds = (fd_set *) alloca (sizeof (fd_set));
289 if (wfds)
290 for (i = 0; i < wfds->fd_count; i++)
292 fd = wfds->fd_array[i];
293 h = (HANDLE) _get_osfhandle (fd);
294 if (IsConsoleHandle (h)
295 && GetNumberOfConsoleInputEvents (h, &nbuffer))
296 continue;
298 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
299 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
301 else
302 wfds = (fd_set *) alloca (sizeof (fd_set));
304 if (xfds)
305 for (i = 0; i < xfds->fd_count; i++)
307 fd = xfds->fd_array[i];
308 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
309 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
311 else
312 xfds = (fd_set *) alloca (sizeof (fd_set));
314 /* Zero all the fd_sets, including the application's. */
315 FD_ZERO (rfds);
316 FD_ZERO (wfds);
317 FD_ZERO (xfds);
318 FD_ZERO (&handle_rfds);
319 FD_ZERO (&handle_wfds);
320 FD_ZERO (&handle_xfds);
322 /* Classify handles. Create fd sets for sockets, poll the others. */
323 for (i = 0; i < nfds; i++)
325 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
326 continue;
328 h = (HANDLE) _get_osfhandle (i);
329 if (!h)
331 errno = EBADF;
332 return -1;
335 if (IsSocketHandle (h))
337 int requested = FD_CLOSE;
339 /* See above; socket handles are mapped onto select, but we
340 need to map descriptors to handles. */
341 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
343 requested |= FD_READ | FD_ACCEPT;
344 FD_SET ((SOCKET) h, rfds);
345 FD_SET ((SOCKET) h, &handle_rfds);
347 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
349 requested |= FD_WRITE | FD_CONNECT;
350 FD_SET ((SOCKET) h, wfds);
351 FD_SET ((SOCKET) h, &handle_wfds);
353 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
355 requested |= FD_OOB;
356 FD_SET ((SOCKET) h, xfds);
357 FD_SET ((SOCKET) h, &handle_xfds);
360 WSAEventSelect ((SOCKET) h, hEvent, requested);
361 nsock++;
363 else
365 handle_array[nhandles++] = h;
367 /* Poll now. If we get an event, do not wait below. */
368 if (wait_timeout != 0
369 && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
370 wait_timeout = 0;
374 if (wait_timeout == 0 || nsock == 0)
375 rc = 0;
376 else
378 /* See if we need to wait in the loop below. If any select is ready,
379 do MsgWaitForMultipleObjects anyway to dispatch messages, but
380 no need to call select again. */
381 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
382 if (rc == 0)
384 /* Restore the fd_sets for the other select we do below. */
385 memcpy (&handle_rfds, rfds, sizeof (fd_set));
386 memcpy (&handle_wfds, wfds, sizeof (fd_set));
387 memcpy (&handle_xfds, xfds, sizeof (fd_set));
389 else
390 wait_timeout = 0;
393 for (;;)
395 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
396 wait_timeout, QS_ALLINPUT);
398 if (ret == WAIT_OBJECT_0 + nhandles)
400 /* new input of some other kind */
401 BOOL bRet;
402 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
404 TranslateMessage (&msg);
405 DispatchMessage (&msg);
408 else
409 break;
412 /* If we haven't done it yet, check the status of the sockets. */
413 if (rc == 0 && nsock > 0)
414 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
416 /* Now fill in the results. */
417 FD_ZERO (rfds);
418 FD_ZERO (wfds);
419 FD_ZERO (xfds);
421 /* Place a sentinel at the end of the array. */
422 handle_array[nhandles] = NULL;
423 nhandles = 1;
424 for (i = 0; i < nfds; i++)
426 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
427 continue;
429 h = (HANDLE) _get_osfhandle (i);
430 if (h != handle_array[nhandles])
432 /* Perform handle->descriptor mapping. Don't update rc, as these
433 results are counted in the return value of Winsock's select. */
434 WSAEventSelect ((SOCKET) h, NULL, 0);
435 if (FD_ISSET (h, &handle_rfds))
436 FD_SET (i, rfds);
437 if (FD_ISSET (h, &handle_wfds))
438 FD_SET (i, wfds);
439 if (FD_ISSET (h, &handle_xfds))
440 FD_SET (i, xfds);
442 else
444 /* Not a socket. */
445 nhandles++;
446 win32_poll_handle (h, i, &rbits, &wbits, &xbits);
447 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
449 rc++;
450 FD_SET (i, rfds);
452 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
454 rc++;
455 FD_SET (i, wfds);
457 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
459 rc++;
460 FD_SET (i, xfds);
465 return rc;
468 #else /* ! Native Win32. */
470 #include <sys/select.h>
472 #undef select
475 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
476 struct timeval *timeout)
478 /* Interix 3.5 has a bug: it does not support nfds == 0. */
479 if (nfds == 0)
481 nfds = 1;
482 rfds = NULL;
483 wfds = NULL;
484 xfds = NULL;
486 return select (nfds, rfds, wfds, xfds, timeout);
489 #endif