Rename lib/winsock-select.c to lib/select.c.
[gnulib.git] / lib / select.c
1 /* Emulation for select(2)
2    Contributed by Paolo Bonzini.
3
4    Copyright 2008 Free Software Foundation, Inc.
5
6    This file is part of gnulib.
7
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 2, or (at your option)
11    any later version.
12
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.
17
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.  */
21
22 #include <config.h>
23 #include <alloca.h>
24
25 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
26 #include <sys/types.h>
27 #include <stdbool.h>
28 #include <errno.h>
29 #include <limits.h>
30
31 #include <winsock2.h>
32 #include <windows.h>
33 #include <io.h>
34 #include <stdio.h>
35 #include <conio.h>
36 #include <time.h>
37
38 struct bitset {
39   unsigned char in[FD_SETSIZE / CHAR_BIT];
40   unsigned char out[FD_SETSIZE / CHAR_BIT];
41 };
42
43 /* Declare data structures for ntdll functions.  */
44 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
45   ULONG NamedPipeType;
46   ULONG NamedPipeConfiguration;
47   ULONG MaximumInstances;
48   ULONG CurrentInstances;
49   ULONG InboundQuota;
50   ULONG ReadDataAvailable;
51   ULONG OutboundQuota;
52   ULONG WriteQuotaAvailable;
53   ULONG NamedPipeState;
54   ULONG NamedPipeEnd;
55 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
56
57 typedef struct _IO_STATUS_BLOCK
58 {
59   union {
60     DWORD Status;
61     PVOID Pointer;
62   } u;
63   ULONG_PTR Information;
64 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
65
66 typedef enum _FILE_INFORMATION_CLASS {
67   FilePipeLocalInformation = 24
68 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
69
70 typedef DWORD (WINAPI *PNtQueryInformationFile)
71          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
72
73 #ifndef PIPE_BUF
74 #define PIPE_BUF        512
75 #endif
76
77 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
78
79 static int
80 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
81                    struct bitset *xbits)
82 {
83   BOOL read, write, except;
84   int i, ret;
85   INPUT_RECORD *irbuffer;
86   DWORD avail, nbuffer;
87   BOOL bRet;
88   IO_STATUS_BLOCK iosb;
89   FILE_PIPE_LOCAL_INFORMATION fpli;
90   static PNtQueryInformationFile NtQueryInformationFile;
91   static BOOL once_only;
92
93   read = write = except = FALSE;
94   switch (GetFileType (h))
95     {
96     case FILE_TYPE_DISK:
97       read = TRUE;
98       write = TRUE;
99       break;
100
101     case FILE_TYPE_PIPE:
102       if (!once_only)
103         {
104           NtQueryInformationFile = (PNtQueryInformationFile)
105             GetProcAddress (GetModuleHandle ("ntdll.dll"),
106                             "NtQueryInformationFile");
107           once_only = TRUE;
108         }
109
110       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
111         {
112           if (avail)
113             read = TRUE;
114         }
115
116       else
117         {
118           /* It was the write-end of the pipe.  Check if it is writable.
119              If NtQueryInformationFile fails, optimistically assume the pipe is
120              writable.  This could happen on Win9x, where NtQueryInformationFile
121              is not available, or if we inherit a pipe that doesn't permit
122              FILE_READ_ATTRIBUTES access on the write end (I think this should
123              not happen since WinXP SP2; WINE seems fine too).  Otherwise,
124              ensure that enough space is available for atomic writes.  */
125           memset (&iosb, 0, sizeof (iosb));
126           memset (&fpli, 0, sizeof (fpli));
127
128           if (!NtQueryInformationFile
129               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
130                                          FilePipeLocalInformation)
131               || fpli.WriteQuotaAvailable >= PIPE_BUF
132               || (fpli.OutboundQuota < PIPE_BUF &&
133                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
134             write = TRUE;
135         }
136       break;
137
138     case FILE_TYPE_CHAR:
139       ret = WaitForSingleObject (h, 0);
140       write = TRUE;
141       if (ret == WAIT_OBJECT_0)
142         {
143           nbuffer = avail = 0;
144           bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
145           if (!bRet || nbuffer == 0)
146             except = TRUE;
147
148           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
149           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
150           if (!bRet || avail == 0)
151             except = TRUE;
152
153           for (i = 0; i < avail; i++)
154             if (irbuffer[i].EventType == KEY_EVENT)
155               read = TRUE;
156         }
157       break;
158
159     default:
160       ret = WaitForSingleObject (h, 0);
161       write = TRUE;
162       if (ret == WAIT_OBJECT_0)
163         read = TRUE;
164
165       break;
166     }
167
168   ret = 0;
169   if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
170     {
171       rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
172       ret++;
173     }
174
175   if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
176     {
177       wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
178       ret++;
179     }
180
181   if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
182     {
183       xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
184       ret++;
185     }
186
187   return ret;
188 }
189
190 int
191 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
192             struct timeval *timeout)
193 {
194   static struct timeval tv0;
195   static HANDLE hEvent;
196   HANDLE h, handle_array[FD_SETSIZE + 2];
197   fd_set handle_rfds, handle_wfds, handle_xfds;
198   struct bitset rbits, wbits, xbits;
199   unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
200   DWORD ret, wait_timeout, nhandles, nsock;
201   MSG msg;
202   int i, fd, rc;
203
204   if (nfds > FD_SETSIZE)
205     nfds = FD_SETSIZE;
206
207   if (!timeout)
208     wait_timeout = INFINITE;
209   else
210     {
211       wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
212
213       /* select is also used as a portable usleep.  */
214       if (!rfds && !wfds && !xfds)
215         {
216           Sleep (wait_timeout);
217           return 0;
218         }
219     }
220
221   if (!hEvent)
222     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
223
224   handle_array[0] = hEvent;
225   nhandles = 1;
226   nsock = 0;
227
228   /* Copy descriptors to bitsets.  */
229   memset (&rbits, 0, sizeof (rbits));
230   memset (&wbits, 0, sizeof (wbits));
231   memset (&xbits, 0, sizeof (xbits));
232   memset (anyfds_in, 0, sizeof (anyfds_in));
233   if (rfds)
234     for (i = 0; i < rfds->fd_count; i++)
235       {
236         fd = rfds->fd_array[i];
237         rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
238         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
239       }
240   else
241     rfds = (fd_set *) alloca (sizeof (fd_set));
242
243   if (wfds)
244     for (i = 0; i < wfds->fd_count; i++)
245       {
246         fd = wfds->fd_array[i];
247         wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
248         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
249       }
250   else
251     wfds = (fd_set *) alloca (sizeof (fd_set));
252
253   if (xfds)
254     for (i = 0; i < xfds->fd_count; i++)
255       {
256         fd = xfds->fd_array[i];
257         xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
258         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
259       }
260   else
261     xfds = (fd_set *) alloca (sizeof (fd_set));
262
263   /* Zero all the fd_sets, including the application's.  */
264   FD_ZERO (rfds);
265   FD_ZERO (wfds);
266   FD_ZERO (xfds);
267   FD_ZERO (&handle_rfds);
268   FD_ZERO (&handle_wfds);
269   FD_ZERO (&handle_xfds);
270
271   /* Classify handles.  Create fd sets for sockets, poll the others. */
272   for (i = 0; i < nfds; i++)
273     {
274       WSANETWORKEVENTS ev;
275
276       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
277         continue;
278
279       h = (HANDLE) _get_osfhandle (i);
280       if (!h)
281         {
282           errno = EBADF;
283           return -1;
284         }
285
286       /* Under Wine, it seems that getsockopt returns 0 for pipes too.
287          WSAEnumNetworkEvents instead distinguishes the two correctly.  */
288       ev.lNetworkEvents = 0xDEADBEEF;
289       WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
290       if (ev.lNetworkEvents != 0xDEADBEEF)
291         {
292           int requested = FD_CLOSE;
293
294           /* See above; socket handles are mapped onto select, but we
295              need to map descriptors to handles.  */
296           if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
297             {
298               requested |= FD_READ | FD_ACCEPT;
299               FD_SET ((SOCKET) h, rfds);
300               FD_SET ((SOCKET) h, &handle_rfds);
301             }
302           if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
303             {
304               requested |= FD_WRITE | FD_CONNECT;
305               FD_SET ((SOCKET) h, wfds);
306               FD_SET ((SOCKET) h, &handle_wfds);
307             }
308           if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
309             {
310               requested |= FD_OOB;
311               FD_SET ((SOCKET) h, xfds);
312               FD_SET ((SOCKET) h, &handle_xfds);
313             }
314
315           WSAEventSelect ((SOCKET) h, hEvent, requested);
316           nsock++;
317         }
318       else
319         {
320           handle_array[nhandles++] = h;
321
322           /* Poll now.  If we get an event, do not wait below.  */
323           if (wait_timeout != 0
324               && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
325             wait_timeout = 0;
326         }
327     }
328
329   if (wait_timeout == 0 || nsock == 0)
330     rc = 0;
331   else
332     {
333       /* See if we need to wait in the loop below.  If any select is ready,
334          do MsgWaitForMultipleObjects anyway to dispatch messages, but
335          no need to call select again.  */
336       rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
337       if (rc == 0)
338         {
339           /* Restore the fd_sets for the other select we do below.  */
340           memcpy (&handle_rfds, rfds, sizeof (fd_set));
341           memcpy (&handle_wfds, wfds, sizeof (fd_set));
342           memcpy (&handle_xfds, xfds, sizeof (fd_set));
343         }
344       else
345         wait_timeout = 0;
346     }
347
348   for (;;)
349     {
350       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
351                                        wait_timeout, QS_ALLINPUT);
352
353       if (ret == WAIT_OBJECT_0 + nhandles)
354         {
355           /* new input of some other kind */
356           BOOL bRet;
357           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
358             {
359               TranslateMessage (&msg);
360               DispatchMessage (&msg);
361             }
362         }
363       else
364         break;
365     }
366
367   /* If we haven't done it yet, check the status of the sockets.  */
368   if (rc == 0 && nsock > 0)
369     rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
370
371   /* Now fill in the results.  */
372   FD_ZERO (rfds);
373   FD_ZERO (wfds);
374   FD_ZERO (xfds);
375
376   /* Place a sentinel at the end of the array.  */
377   handle_array[nhandles] = NULL;
378   nhandles = 1;
379   for (i = 0; i < nfds; i++)
380     {
381       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
382         continue;
383
384       h = (HANDLE) _get_osfhandle (i);
385       if (h != handle_array[nhandles])
386         {
387           /* Perform handle->descriptor mapping.  Don't update rc, as these
388              results are counted in the return value of Winsock's select.  */
389           WSAEventSelect ((SOCKET) h, NULL, 0);
390           if (FD_ISSET (h, &handle_rfds))
391             FD_SET (i, rfds);
392           if (FD_ISSET (h, &handle_wfds))
393             FD_SET (i, wfds);
394           if (FD_ISSET (h, &handle_xfds))
395             FD_SET (i, xfds);
396         }
397       else
398         {
399           /* Not a socket.  */
400           nhandles++;
401           win32_poll_handle (h, i, &rbits, &wbits, &xbits);
402           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
403             {
404               rc++;
405               FD_SET (i, rfds);
406             }
407           if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
408             {
409               rc++;
410               FD_SET (i, wfds);
411             }
412           if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
413             {
414               rc++;
415               FD_SET (i, xfds);
416             }
417         }
418     }
419
420   return rc;
421 }
422
423 #endif /* Native Win32.  */