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 */
26 #include <sys/socket.h>
42 # define FD_TO_SOCKET(fd) ((SOCKET) _get_osfhandle ((fd)))
43 # define SOCKET_TO_FD(fh) (_open_osfhandle ((long) (fh), O_RDWR | O_BINARY))
46 /* Hook for gnulib module close. */
48 #if HAVE__GL_CLOSE_FD_MAYBE_SOCKET
50 _gl_close_fd_maybe_socket (int fd)
52 SOCKET sock = FD_TO_SOCKET (fd);
55 ev.lNetworkEvents = 0xDEADBEEF;
56 WSAEnumNetworkEvents (sock, NULL, &ev);
57 if (ev.lNetworkEvents != 0xDEADBEEF)
59 /* FIXME: other applications, like squid, use an undocumented
60 _free_osfhnd free function. Instead, here we just close twice
61 the file descriptor. I could not get the former to work
63 int r = closesocket (sock);
73 /* Wrappers for WinSock functions. */
76 set_winsock_errno (void)
78 int err = WSAGetLastError ();
81 /* Map some WSAE* errors to the runtime library's error codes. */
84 case WSA_INVALID_HANDLE:
87 case WSA_NOT_ENOUGH_MEMORY:
90 case WSA_INVALID_PARAMETER:
103 errno = (err > 10000 && err < 10025) ? err - 10000 : err;
110 rpl_socket (int domain, int type, int protocol)
112 /* We have to use WSASocket() to create non-overlapped IO sockets.
113 Overlapped IO sockets cannot be used with read/write. */
114 SOCKET fh = WSASocket (domain, type, protocol, NULL, 0, 0);
116 if (fh == INVALID_SOCKET)
118 set_winsock_errno ();
122 return SOCKET_TO_FD (fh);
128 rpl_connect (int fd, struct sockaddr *sockaddr, int len)
130 SOCKET sock = FD_TO_SOCKET (fd);
131 int r = connect (sock, sockaddr, len);
134 /* EINPROGRESS is not returned by WinSock 2.0; for backwards
135 compatibility, connect(2) uses EWOULDBLOCK. */
136 if (WSAGetLastError () == WSAEWOULDBLOCK)
137 WSASetLastError (WSAEINPROGRESS);
139 set_winsock_errno ();
148 rpl_accept (int fd, struct sockaddr *addr, int *addrlen)
150 SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
151 if (fh == INVALID_SOCKET)
153 set_winsock_errno ();
157 return SOCKET_TO_FD (fh);
163 rpl_bind (int fd, struct sockaddr *sockaddr, int len)
165 SOCKET sock = FD_TO_SOCKET (fd);
166 int r = bind (sock, sockaddr, len);
168 set_winsock_errno ();
174 #if GNULIB_GETPEERNAME
176 rpl_getpeername (int fd, struct sockaddr *addr, int *addrlen)
178 SOCKET sock = FD_TO_SOCKET (fd);
179 int r = getpeername (sock, addr, addrlen);
181 set_winsock_errno ();
187 #if GNULIB_GETSOCKNAME
189 rpl_getsockname (int fd, struct sockaddr *addr, int *addrlen)
191 SOCKET sock = FD_TO_SOCKET (fd);
192 int r = getsockname (sock, addr, addrlen);
194 set_winsock_errno ();
200 #if GNULIB_GETSOCKOPT
202 rpl_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
204 SOCKET sock = FD_TO_SOCKET (fd);
205 int r = getsockopt (sock, level, optname, optval, optlen);
207 set_winsock_errno ();
215 rpl_listen (int fd, int backlog)
217 SOCKET sock = FD_TO_SOCKET (fd);
218 int r = listen (sock, backlog);
220 set_winsock_errno ();
227 rpl_ioctl (int fd, unsigned long req, char *buf)
229 SOCKET sock = FD_TO_SOCKET (fd);
230 int r = ioctlsocket (sock, req, (void *) buf);
232 set_winsock_errno ();
239 rpl_recv (int fd, void *buf, int len, int flags)
241 SOCKET sock = FD_TO_SOCKET (fd);
242 int r = recv (sock, buf, len, flags);
244 set_winsock_errno ();
252 rpl_send (int fd, const void *buf, int len, int flags)
254 SOCKET sock = FD_TO_SOCKET (fd);
255 int r = send (sock, buf, len, flags);
257 set_winsock_errno ();
265 rpl_recvfrom (int fd, void *buf, int len, int flags, struct sockaddr *from,
268 int frombufsize = *fromlen;
269 SOCKET sock = FD_TO_SOCKET (fd);
270 int r = recvfrom (sock, buf, len, flags, from, fromlen);
273 set_winsock_errno ();
275 /* Winsock recvfrom() only returns a valid 'from' when the socket is
276 connectionless. POSIX gives a valid 'from' for all types of sockets. */
277 else if (*fromlen == frombufsize)
278 rpl_getpeername (fd, from, fromlen);
286 rpl_sendto (int fd, const void *buf, int len, int flags,
287 struct sockaddr *to, int tolen)
289 SOCKET sock = FD_TO_SOCKET (fd);
290 int r = sendto (sock, buf, len, flags, to, tolen);
292 set_winsock_errno ();
298 #if GNULIB_SETSOCKOPT
300 rpl_setsockopt (int fd, int level, int optname, const void *optval, int optlen)
302 SOCKET sock = FD_TO_SOCKET (fd);
303 int r = setsockopt (sock, level, optname, optval, optlen);
305 set_winsock_errno ();