1 /* winsock.c --- wrappers for Windows socket functions
3 Copyright (C) 2008 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Written by Paolo Bonzini */
27 #include <sys/socket.h>
29 #include <sys/ioctl.h>
47 #define FD_TO_SOCKET(fd) ((SOCKET) _get_osfhandle ((fd)))
48 #define SOCKET_TO_FD(fh) (_open_osfhandle ((long) (fh), O_RDWR | O_BINARY))
52 set_winsock_errno (void)
54 int err = WSAGetLastError ();
57 /* Map some WSAE* errors to the runtime library's error codes. */
60 case WSA_INVALID_HANDLE:
63 case WSA_NOT_ENOUGH_MEMORY:
66 case WSA_INVALID_PARAMETER:
79 errno = (err > 10000 && err < 10025) ? err - 10000 : err;
85 /* Hook for gnulib module close. */
87 #if HAVE__GL_CLOSE_FD_MAYBE_SOCKET
89 _gl_close_fd_maybe_socket (int fd)
91 SOCKET sock = FD_TO_SOCKET (fd);
94 ev.lNetworkEvents = 0xDEADBEEF;
95 WSAEnumNetworkEvents (sock, NULL, &ev);
96 if (ev.lNetworkEvents != 0xDEADBEEF)
98 /* FIXME: other applications, like squid, use an undocumented
99 _free_osfhnd free function. But this is not enough: The 'osfile'
100 flags for fd also needs to be cleared, but it is hard to access it.
101 Instead, here we just close twice the file descriptor. */
102 if (closesocket (sock))
104 set_winsock_errno ();
109 /* This call frees the file descriptor and does a
110 CloseHandle ((HANDLE) _get_osfhandle (fd)), which fails. */
121 /* Wrappers for WinSock functions. */
125 rpl_socket (int domain, int type, int protocol)
127 /* We have to use WSASocket() to create non-overlapped IO sockets.
128 Overlapped IO sockets cannot be used with read/write. */
129 SOCKET fh = WSASocket (domain, type, protocol, NULL, 0, 0);
131 if (fh == INVALID_SOCKET)
133 set_winsock_errno ();
137 return SOCKET_TO_FD (fh);
143 rpl_connect (int fd, struct sockaddr *sockaddr, int len)
145 SOCKET sock = FD_TO_SOCKET (fd);
146 int r = connect (sock, sockaddr, len);
149 /* EINPROGRESS is not returned by WinSock 2.0; for backwards
150 compatibility, connect(2) uses EWOULDBLOCK. */
151 if (WSAGetLastError () == WSAEWOULDBLOCK)
152 WSASetLastError (WSAEINPROGRESS);
154 set_winsock_errno ();
163 rpl_accept (int fd, struct sockaddr *addr, int *addrlen)
165 SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
166 if (fh == INVALID_SOCKET)
168 set_winsock_errno ();
172 return SOCKET_TO_FD (fh);
178 rpl_bind (int fd, struct sockaddr *sockaddr, int len)
180 SOCKET sock = FD_TO_SOCKET (fd);
181 int r = bind (sock, sockaddr, len);
183 set_winsock_errno ();
189 #if GNULIB_GETPEERNAME
191 rpl_getpeername (int fd, struct sockaddr *addr, int *addrlen)
193 SOCKET sock = FD_TO_SOCKET (fd);
194 int r = getpeername (sock, addr, addrlen);
196 set_winsock_errno ();
202 #if GNULIB_GETSOCKNAME
204 rpl_getsockname (int fd, struct sockaddr *addr, int *addrlen)
206 SOCKET sock = FD_TO_SOCKET (fd);
207 int r = getsockname (sock, addr, addrlen);
209 set_winsock_errno ();
215 #if GNULIB_GETSOCKOPT
217 rpl_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
219 SOCKET sock = FD_TO_SOCKET (fd);
220 int r = getsockopt (sock, level, optname, optval, optlen);
222 set_winsock_errno ();
230 rpl_listen (int fd, int backlog)
232 SOCKET sock = FD_TO_SOCKET (fd);
233 int r = listen (sock, backlog);
235 set_winsock_errno ();
243 rpl_ioctl (int fd, int req, ...)
250 va_start (args, req);
251 buf = va_arg (args, void *);
254 sock = FD_TO_SOCKET (fd);
255 r = ioctlsocket (sock, req, buf);
257 set_winsock_errno ();
265 rpl_recv (int fd, void *buf, int len, int flags)
267 SOCKET sock = FD_TO_SOCKET (fd);
268 int r = recv (sock, buf, len, flags);
270 set_winsock_errno ();
278 rpl_send (int fd, const void *buf, int len, int flags)
280 SOCKET sock = FD_TO_SOCKET (fd);
281 int r = send (sock, buf, len, flags);
283 set_winsock_errno ();
291 rpl_recvfrom (int fd, void *buf, int len, int flags, struct sockaddr *from,
294 int frombufsize = *fromlen;
295 SOCKET sock = FD_TO_SOCKET (fd);
296 int r = recvfrom (sock, buf, len, flags, from, fromlen);
299 set_winsock_errno ();
301 /* Winsock recvfrom() only returns a valid 'from' when the socket is
302 connectionless. POSIX gives a valid 'from' for all types of sockets. */
303 else if (*fromlen == frombufsize)
304 rpl_getpeername (fd, from, fromlen);
312 rpl_sendto (int fd, const void *buf, int len, int flags,
313 struct sockaddr *to, int tolen)
315 SOCKET sock = FD_TO_SOCKET (fd);
316 int r = sendto (sock, buf, len, flags, to, tolen);
318 set_winsock_errno ();
324 #if GNULIB_SETSOCKOPT
326 rpl_setsockopt (int fd, int level, int optname, const void *optval, int optlen)
328 SOCKET sock = FD_TO_SOCKET (fd);
329 int r = setsockopt (sock, level, optname, optval, optlen);
331 set_winsock_errno ();
339 rpl_shutdown (int fd, int how)
341 SOCKET sock = FD_TO_SOCKET (fd);
342 int r = shutdown (sock, how);
344 set_winsock_errno ();