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>
44 # define FD_TO_SOCKET(fd) ((SOCKET) _get_osfhandle ((fd)))
45 # define SOCKET_TO_FD(fh) (_open_osfhandle ((long) (fh), O_RDWR | O_BINARY))
48 /* Wrappers for libc functions. */
53 char buf[sizeof (int)];
54 SOCKET sock = FD_TO_SOCKET (fd);
57 ev.lNetworkEvents = 0xDEADBEEF;
58 WSAEnumNetworkEvents (sock, NULL, &ev);
59 if (ev.lNetworkEvents != 0xDEADBEEF)
61 /* FIXME: other applications, like squid, use an undocumented
62 _free_osfhnd free function. Instead, here we just close twice
63 the file descriptor. I could not get the former to work
65 int r = closesocket (sock);
74 /* Wrappers for WinSock functions. */
77 set_winsock_errno (void)
79 int err = WSAGetLastError ();
82 /* Map some WSAE* errors to the runtime library's error codes. */
85 case WSA_INVALID_HANDLE:
88 case WSA_NOT_ENOUGH_MEMORY:
91 case WSA_INVALID_PARAMETER:
101 errno = (err > 10000 && err < 10025) ? err - 10000 : err;
107 rpl_socket (int domain, int type, int protocol)
109 /* We have to use WSASocket() to create non-overlapped IO sockets.
110 Overlapped IO sockets cannot be used with read/write. */
111 SOCKET fh = WSASocket (domain, type, protocol, NULL, 0, 0);
113 if (fh == INVALID_SOCKET)
115 set_winsock_errno ();
119 return SOCKET_TO_FD (fh);
124 rpl_connect (int fd, struct sockaddr *sockaddr, int len)
126 SOCKET sock = FD_TO_SOCKET (fd);
127 int r = connect (sock, sockaddr, len);
130 /* EINPROGRESS is not returned by WinSock 2.0; for backwards
131 compatibility, connect(2) uses EWOULDBLOCK. */
132 if (WSAGetLastError () == WSAEWOULDBLOCK)
133 WSASetLastError (WSAEINPROGRESS);
135 set_winsock_errno ();
142 rpl_accept (int fd, struct sockaddr *addr, int *addrlen)
144 SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
145 if (fh == INVALID_SOCKET)
147 set_winsock_errno ();
151 return SOCKET_TO_FD (fh);
155 rpl_bind (int fd, struct sockaddr *sockaddr, int len)
157 SOCKET sock = FD_TO_SOCKET (fd);
158 int r = bind (sock, sockaddr, len);
160 set_winsock_errno ();
166 rpl_getpeername (int fd, struct sockaddr *addr, int *addrlen)
168 SOCKET sock = FD_TO_SOCKET (fd);
169 int r = getpeername (sock, addr, addrlen);
171 set_winsock_errno ();
177 rpl_getsockname (int fd, struct sockaddr *addr, int *addrlen)
179 SOCKET sock = FD_TO_SOCKET (fd);
180 int r = getsockname (sock, addr, addrlen);
182 set_winsock_errno ();
188 rpl_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
190 SOCKET sock = FD_TO_SOCKET (fd);
191 int r = getsockopt (sock, level, optname, optval, optlen);
193 set_winsock_errno ();
199 rpl_listen (int fd, int backlog)
201 SOCKET sock = FD_TO_SOCKET (fd);
202 int r = listen (sock, backlog);
204 set_winsock_errno ();
210 rpl_ioctl (int fd, unsigned long req, char *buf)
212 SOCKET sock = FD_TO_SOCKET (fd);
213 int r = ioctlsocket (sock, req, (void *) buf);
215 set_winsock_errno ();
221 rpl_recv (int fd, void *buf, int len, int flags)
223 SOCKET sock = FD_TO_SOCKET (fd);
224 int r = recv (sock, buf, len, flags);
226 set_winsock_errno ();
232 rpl_send (int fd, const void *buf, int len, int flags)
234 SOCKET sock = FD_TO_SOCKET (fd);
235 int r = send (sock, buf, len, flags);
237 set_winsock_errno ();
243 rpl_recvfrom (int fd, void *buf, int len, int flags, struct sockaddr *from,
246 int frombufsize = *fromlen;
247 SOCKET sock = FD_TO_SOCKET (fd);
248 int r = recvfrom (sock, buf, len, flags, from, fromlen);
251 set_winsock_errno ();
253 /* Winsock recvfrom() only returns a valid 'from' when the socket is
254 connectionless. POSIX gives a valid 'from' for all types of sockets. */
255 else if (*fromlen == frombufsize)
256 rpl_getpeername (fd, from, fromlen);
262 rpl_sendto (int fd, const void *buf, int len, int flags,
263 struct sockaddr *to, int tolen)
265 SOCKET sock = FD_TO_SOCKET (fd);
266 int r = sendto (sock, buf, len, flags, to, tolen);
268 set_winsock_errno ();
274 rpl_setsockopt (int fd, int level, int optname, const void *optval, int optlen)
276 SOCKET sock = FD_TO_SOCKET (fd);
277 int r = setsockopt (sock, level, optname, optval, optlen);
279 set_winsock_errno ();