]> git.sesse.net Git - vlc/blob - src/network/poll.c
Improve Win32 poll replacement (and fix #1949)
[vlc] / src / network / poll.c
1 /*****************************************************************************
2  * poll.c: I/O event multiplexing
3  *****************************************************************************
4  * Copyright © 2007-2008 Rémi Denis-Courmont
5  * $Id$
6  *
7  * Author: Rémi Denis-Courmont
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <vlc_common.h>
29 #include <vlc_network.h>
30
31 #ifndef WIN32
32 struct pollfd;
33
34 int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
35 {
36     (void)fds; (void)nfds; (void)timeout;
37     abort ();
38 }
39 #else
40 #include <string.h>
41 #include <stdlib.h>
42 #include <vlc_network.h>
43
44 int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
45 {
46     WSAEVENT phEvents[nfds];
47     DWORD val;
48
49     for (unsigned i = 0; i < nfds; i++)
50     {
51         long events = FD_CLOSE;
52
53         if (fds[i].events & POLLIN)
54             events |= FD_READ | FD_ACCEPT;
55         if (fds[i].events & POLLOUT)
56             events |= FD_WRITE;
57         if (fds[i].events & POLLPRI)
58             events |= FD_OOB;
59         fds[i].revents = 0;
60
61         phEvents[i] = WSACreateEvent ();
62         WSAEventSelect (fds[i].fd, phEvents[i], events);
63     }
64
65     switch (WaitForMultipleObjectsEx (nfds, phEvents, FALSE, timeout, TRUE))
66     {
67       case WAIT_IO_COMPLETION:
68         WSASetLastError (WSAEINTR);
69         return -1;
70       case WAIT_TIMEOUT:
71         return 0;
72     }
73
74     int n = 0, err = 0;
75
76     for (unsigned i = 0; i < nfds; i++)
77     {
78         WSANETWORKEVENTS events;
79         err = WSAEnumNetworkEvents (fds[i].fd, phEvents[i], &events);
80         WSACloseEvent (phEvents[i]);
81         if (err)
82         {
83             fds[i].revents |= POLLNVAL;
84             continue;
85         }
86         if (events.lNetworkEvents & FD_CLOSE)
87             fds[i].revents |= POLLHUP | (fds[i].events & POLLIN);
88         if (events.lNetworkEvents & FD_ACCEPT)
89             fds[i].revents |= POLLIN;
90         if (events.lNetworkEvents & FD_OOB)
91             fds[i].revents |= POLLPRI;
92         if (events.lNetworkEvents & FD_READ)
93             fds[i].revents |= POLLIN;
94         if (events.lNetworkEvents & FD_WRITE)
95         {
96             fds[i].revents |= POLLOUT;
97             if (events.iErrorCode[FD_WRITE_BIT])
98                 fds[i].revents |= POLLERR;
99         }
100         if (fds[i].events)
101             n++;
102     }
103     return err ? -1 : n;
104 }
105 #endif /* WIN32 */