1 /* GnuTLS modifications: */
2 #define SetErrnoFromWinsockError(x) errno = EIO;
3 #define SetErrnoFromWinError(x) x
10 #include <sys/types.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).
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
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
;
72 struct timeval tvslice
;
75 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
81 /* calculate how long we need to wait in milliseconds */
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
))
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
))
110 if (ioctlsocket(i
, FIONREAD
, &ulVal
) != SOCKET_ERROR
&& _get_osfhandle(i
) == -1)
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
);
127 if (GetFileType((HANDLE
) i
) == FILE_TYPE_PIPE
)
128 hPipes
[iPipes
++] = (HANDLE
) i
; /* Pipe */
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
;
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());
149 /* mixture of handles and sockets; lets multiplex between
150 * winsock and waiting on the handles */
156 limit
= GetTickCount() + ms_total
;
163 /* overwrite the zero'd sets here; the select call
164 * will clear those that are not active */
167 aexcept
= sock_except
;
170 tvslice
.tv_usec
= 100000;
172 if ((retcode
= select(sock_max_fd
+ 1, &aread
, &awrite
, &aexcept
,
173 &tvslice
)) == SOCKET_ERROR
)
175 SetErrnoFromWinsockError(WSAGetLastError());
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
198 else if(wret
== WAIT_FAILED
)
200 SetErrnoFromWinError(GetLastError());
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
);
228 for(i
= 0; i
< iPipes
; i
++)
231 if(SAFE_FD_ISSET(hPipes
[i
], rfds
))
233 if (! PeekNamedPipe(hPipes
[i
], NULL
, 0, NULL
, &dwBytes
, NULL
))
236 SetErrnoFromWinError(GetLastError());
240 FD_SET((int) hPipes
[i
], &aread
);
244 else if (SAFE_FD_ISSET(hPipes
[i
], wfds
) || SAFE_FD_ISSET(hPipes
[i
], efds
))
247 return -1; /* Not implemented */
251 while(retcode
== 0 && (ms_total
== INFINITE
|| GetTickCount() < limit
));
265 #endif /* _WIN32 || defined __WIN32__ */