Fix memory leak.
[gnutls.git] / src / select.c
blobd310409cb6d2e7e2ddeccf22c62598b4cd357746
1 /* GnuTLS modifications: */
2 #define SetErrnoFromWinsockError(x) errno = EIO;
3 #define SetErrnoFromWinError(x) x
5 #include <config.h>
7 #include <stdio.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <string.h>
12 #include <unistd.h>
14 #include "common.h"
16 #if defined _WIN32 || defined __WIN32__
19 This file is part of PlibC.
20 (C) 2005, 2006 Nils Durner (and other contributing authors)
22 This library is free software; you can redistribute it and/or
23 modify it under the terms of the GNU Lesser General Public
24 License as published by the Free Software Foundation; either
25 version 2.1 of the License, or (at your option) any later version.
27 This library is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 Lesser General Public License for more details.
32 You should have received a copy of the GNU Lesser General Public
33 License along with this library; if not, write to the Free Software
34 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 * Code originally written by Wez Furlong <wez@thebrainroom.com>
39 * who originally placed it under the PHP License Version 3.0.
40 * Adapted for GNUnet by Nils Durner <durner@gnunet.org>.
41 * GPLed with permission from Wez Furlong (see E-mail on
42 * gnunet-developers, also quoted in the GNUnet CVS logs).
44 * @file src/select.c
45 * @brief select implementation for Win32
46 * @author Wez Furlong <wez@thebrainroom.com>
47 * @author Nils Durner (GNUnet extensions)
51 * Win32 select() will only work with sockets, so we roll our own
52 * implementation here.
53 * - If you supply only sockets, this simply passes through to winsock select().
54 * - If you supply file handles, there is no way to distinguish between
55 * ready for read/write or OOB, so any set in which the handle is found will
56 * be marked as ready.
57 * - If you supply a mixture of handles and sockets, the system will interleave
58 * calls between select() and WaitForMultipleObjects(). The time slicing may
59 * cause this function call to take up to 100 ms longer than you specified.
60 * - Pipes are not checked for writability or errors (errno = ENOSYS)
62 int _win_select(int max_fd, fd_set * rfds, fd_set * wfds, fd_set * efds,
63 const struct timeval *tv)
65 DWORD ms_total, limit;
66 HANDLE handles[MAXIMUM_WAIT_OBJECTS], hPipes[MAXIMUM_WAIT_OBJECTS];
67 int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
68 int n_handles, i, iPipes;
69 fd_set sock_read, sock_write, sock_except;
70 fd_set aread, awrite, aexcept;
71 int sock_max_fd;
72 struct timeval tvslice;
73 int retcode;
75 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
77 n_handles = 0;
78 sock_max_fd = -1;
79 iPipes = 0;
81 /* calculate how long we need to wait in milliseconds */
82 if(tv == NULL)
83 ms_total = INFINITE;
84 else
86 ms_total = tv->tv_sec * 1000;
87 ms_total += tv->tv_usec / 1000;
90 /* select() may be used as a portable way to sleep */
91 if (!(rfds || wfds || efds))
93 Sleep(ms_total);
95 return 0;
98 FD_ZERO(&sock_read);
99 FD_ZERO(&sock_write);
100 FD_ZERO(&sock_except);
102 /* build an array of handles for non-sockets */
103 for(i = 0; i < max_fd; i++)
105 if(SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) ||
106 SAFE_FD_ISSET(i, efds))
108 unsigned long ulVal;
110 if (ioctlsocket(i, FIONREAD, &ulVal) != SOCKET_ERROR && _get_osfhandle(i) == -1)
112 /* socket */
113 if(SAFE_FD_ISSET(i, rfds))
114 FD_SET(i, &sock_read);
116 if(SAFE_FD_ISSET(i, wfds))
117 FD_SET(i, &sock_write);
119 if(SAFE_FD_ISSET(i, efds))
120 FD_SET(i, &sock_except);
122 if(i > sock_max_fd)
123 sock_max_fd = i;
125 else
127 if (GetFileType((HANDLE) i) == FILE_TYPE_PIPE)
128 hPipes[iPipes++] = (HANDLE) i; /* Pipe */
129 else
131 handles[n_handles] = (HANDLE) _get_osfhandle(i);
132 if ((DWORD) handles[n_handles] == 0xffffffff)
133 handles[n_handles] = (HANDLE) i;
134 handle_slot_to_fd[n_handles] = i;
135 n_handles++;
141 if((n_handles == 0) && (iPipes == 0))
143 /* plain sockets only - let winsock handle the whole thing */
144 if ((retcode = select(max_fd, rfds, wfds, efds, tv)) == SOCKET_ERROR)
145 SetErrnoFromWinsockError(WSAGetLastError());
146 return retcode;
149 /* mixture of handles and sockets; lets multiplex between
150 * winsock and waiting on the handles */
152 FD_ZERO(&aread);
153 FD_ZERO(&awrite);
154 FD_ZERO(&aexcept);
156 limit = GetTickCount() + ms_total;
159 retcode = 0;
161 if(sock_max_fd >= 0)
163 /* overwrite the zero'd sets here; the select call
164 * will clear those that are not active */
165 aread = sock_read;
166 awrite = sock_write;
167 aexcept = sock_except;
169 tvslice.tv_sec = 0;
170 tvslice.tv_usec = 100000;
172 if ((retcode = select(sock_max_fd + 1, &aread, &awrite, &aexcept,
173 &tvslice)) == SOCKET_ERROR)
175 SetErrnoFromWinsockError(WSAGetLastError());
177 return -1;
181 if(n_handles > 0)
183 /* check handles */
184 DWORD wret;
186 wret =
187 MsgWaitForMultipleObjects(n_handles, handles, FALSE,
188 retcode > 0 ? 0 : 100, QS_ALLEVENTS);
190 if(wret == WAIT_TIMEOUT)
192 /* set retcode to 0; this is the default.
193 * select() may have set it to something else,
194 * in which case we leave it alone, so this branch
195 * does nothing */
198 else if(wret == WAIT_FAILED)
200 SetErrnoFromWinError(GetLastError());
202 return -1;
204 else
206 for(i = 0; i < n_handles; i++)
208 if(WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0))
210 if(SAFE_FD_ISSET(handle_slot_to_fd[i], rfds))
212 FD_SET(handle_slot_to_fd[i], &aread);
215 if(SAFE_FD_ISSET(handle_slot_to_fd[i], wfds))
216 FD_SET(handle_slot_to_fd[i], &awrite);
218 if(SAFE_FD_ISSET(handle_slot_to_fd[i], efds))
219 FD_SET(handle_slot_to_fd[i], &aexcept);
221 retcode++;
227 /* Poll Pipes */
228 for(i = 0; i < iPipes; i++)
230 DWORD dwBytes;
231 if(SAFE_FD_ISSET(hPipes[i], rfds))
233 if (! PeekNamedPipe(hPipes[i], NULL, 0, NULL, &dwBytes, NULL))
235 retcode = -1;
236 SetErrnoFromWinError(GetLastError());
238 else if (dwBytes)
240 FD_SET((int) hPipes[i], &aread);
241 retcode++;
244 else if (SAFE_FD_ISSET(hPipes[i], wfds) || SAFE_FD_ISSET(hPipes[i], efds))
246 errno = ENOSYS;
247 return -1; /* Not implemented */
251 while(retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));
253 if(rfds)
254 *rfds = aread;
256 if(wfds)
257 *wfds = awrite;
259 if(efds)
260 *efds = aexcept;
262 return retcode;
265 #endif /* _WIN32 || defined __WIN32__ */