Fix previous commit (untested)
[vlc.git] / 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     vlc_testcancel ();
50
51     for (unsigned i = 0; i < nfds; i++)
52     {
53         long events = FD_CLOSE;
54
55         if (fds[i].events & POLLIN)
56             events |= FD_READ | FD_ACCEPT;
57         if (fds[i].events & POLLOUT)
58             events |= FD_WRITE;
59         if (fds[i].events & POLLPRI)
60             events |= FD_OOB;
61         fds[i].revents = 0;
62
63         phEvents[i] = WSACreateEvent ();
64         WSAEventSelect (fds[i].fd, phEvents[i], events);
65     }
66
67     int ret = 0, n;
68
69     switch (WaitForMultipleObjectsEx (nfds, phEvents, FALSE, timeout, TRUE))
70     {
71       case WAIT_IO_COMPLETION:
72         WSASetLastError (WSAEINTR);
73         ret = -1;
74         break;
75       case WAIT_TIMEOUT:
76         ret = 0;
77         break;
78       default:
79         for (unsigned i = 0; i < nfds; i++)
80         {
81             WSANETWORKEVENTS events;
82             if (WSAEnumNetworkEvents (fds[i].fd, phEvents[i], &events))
83             {
84                 fds[i].revents |= POLLNVAL;
85                 ret = -1;
86                 continue;
87             }
88             if (events.lNetworkEvents & FD_CLOSE)
89                fds[i].revents |= POLLHUP | (fds[i].events & POLLIN);
90             if (events.lNetworkEvents & FD_ACCEPT)
91                fds[i].revents |= POLLIN;
92             if (events.lNetworkEvents & FD_OOB)
93                fds[i].revents |= POLLPRI;
94             if (events.lNetworkEvents & FD_READ)
95                fds[i].revents |= POLLIN;
96             if (events.lNetworkEvents & FD_WRITE)
97             {
98                 fds[i].revents |= POLLOUT;
99                 if (events.iErrorCode[FD_WRITE_BIT])
100                     fds[i].revents |= POLLERR;
101             }
102             if (fds[i].events)
103                 n++;
104         }
105         if (ret == 0)
106             ret = n;
107     }
108
109     for (unsigned i = 0; i < nfds; i++)
110         WSACloseEvent (phEvents[i]);
111     vlc_testcancel ();
112
113     return ret;
114 }
115 #endif /* WIN32 */