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:
104 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);
127 rpl_connect (int fd, struct sockaddr *sockaddr, int len)
129 SOCKET sock = FD_TO_SOCKET (fd);
130 int r = connect (sock, sockaddr, len);
133 /* EINPROGRESS is not returned by WinSock 2.0; for backwards
134 compatibility, connect(2) uses EWOULDBLOCK. */
135 if (WSAGetLastError () == WSAEWOULDBLOCK)
136 WSASetLastError (WSAEINPROGRESS);
138 set_winsock_errno ();
145 rpl_accept (int fd, struct sockaddr *addr, int *addrlen)
147 SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
148 if (fh == INVALID_SOCKET)
150 set_winsock_errno ();
154 return SOCKET_TO_FD (fh);
158 rpl_bind (int fd, struct sockaddr *sockaddr, int len)
160 SOCKET sock = FD_TO_SOCKET (fd);
161 int r = bind (sock, sockaddr, len);
163 set_winsock_errno ();
169 rpl_getpeername (int fd, struct sockaddr *addr, int *addrlen)
171 SOCKET sock = FD_TO_SOCKET (fd);
172 int r = getpeername (sock, addr, addrlen);
174 set_winsock_errno ();
180 rpl_getsockname (int fd, struct sockaddr *addr, int *addrlen)
182 SOCKET sock = FD_TO_SOCKET (fd);
183 int r = getsockname (sock, addr, addrlen);
185 set_winsock_errno ();
191 rpl_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
193 SOCKET sock = FD_TO_SOCKET (fd);
194 int r = getsockopt (sock, level, optname, optval, optlen);
196 set_winsock_errno ();
202 rpl_listen (int fd, int backlog)
204 SOCKET sock = FD_TO_SOCKET (fd);
205 int r = listen (sock, backlog);
207 set_winsock_errno ();
213 rpl_ioctl (int fd, unsigned long req, char *buf)
215 SOCKET sock = FD_TO_SOCKET (fd);
216 int r = ioctlsocket (sock, req, (void *) buf);
218 set_winsock_errno ();
224 rpl_recv (int fd, void *buf, int len, int flags)
226 SOCKET sock = FD_TO_SOCKET (fd);
227 int r = recv (sock, buf, len, flags);
229 set_winsock_errno ();
235 rpl_send (int fd, const void *buf, int len, int flags)
237 SOCKET sock = FD_TO_SOCKET (fd);
238 int r = send (sock, buf, len, flags);
240 set_winsock_errno ();
246 rpl_recvfrom (int fd, void *buf, int len, int flags, struct sockaddr *from,
249 int frombufsize = *fromlen;
250 SOCKET sock = FD_TO_SOCKET (fd);
251 int r = recvfrom (sock, buf, len, flags, from, fromlen);
254 set_winsock_errno ();
256 /* Winsock recvfrom() only returns a valid 'from' when the socket is
257 connectionless. POSIX gives a valid 'from' for all types of sockets. */
258 else if (*fromlen == frombufsize)
259 rpl_getpeername (fd, from, fromlen);
265 rpl_sendto (int fd, const void *buf, int len, int flags,
266 struct sockaddr *to, int tolen)
268 SOCKET sock = FD_TO_SOCKET (fd);
269 int r = sendto (sock, buf, len, flags, to, tolen);
271 set_winsock_errno ();
277 rpl_setsockopt (int fd, int level, int optname, const void *optval, int optlen)
279 SOCKET sock = FD_TO_SOCKET (fd);
280 int r = setsockopt (sock, level, optname, optval, optlen);
282 set_winsock_errno ();