1 /*
2  * Socket compat code for win32.
3  *
4  * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef _USUAL_SOCKET_WIN32_H_
20 #define _USUAL_SOCKET_WIN32_H_
21 
22 /* if found, likely a mistake */
23 #undef HAVE_INET_NTOP
24 #undef HAVE_INET_PTON
25 
26 typedef int socklen_t;
27 
28 #define in_addr_t   uint32_t
29 
30 /*
31  * make recvmsg/sendmsg and fd related code compile
32  */
33 
34 struct iovec {
35 	void	*iov_base;	/* Base address. */
36 	size_t	 iov_len;	/* Length. */
37 };
38 
39 struct msghdr {
40 	void         *msg_name;
41 	int	     msg_namelen;
42 	struct iovec *msg_iov;
43 	int           msg_iovlen;
44 	void         *msg_control;
45 	int           msg_controllen;
46 	int           msg_flags;
47 };
48 
49 #ifndef SCM_RIGHTS
50 #define SCM_RIGHTS 1
51 #endif
52 
53 #ifndef CMSG_FIRSTHDR
54 
55 struct cmsghdr {
56 	int		cmsg_len;
57 	int		cmsg_level;
58 	int		cmsg_type;
59 };
60 
61 #define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1))
62 #define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \
63 	& ~(sizeof (size_t) - 1))
64 #define CMSG_LEN(len) ((int)(CMSG_ALIGN(sizeof(struct cmsghdr))+(len)))
65 #define CMSG_FIRSTHDR(mhdr) \
66 	((mhdr)->msg_controllen >= (int)sizeof(struct cmsghdr) ? \
67 	(struct cmsghdr *)(mhdr)->msg_control : \
68 	(struct cmsghdr *)NULL)
69 #define CMSG_NXTHDR(mhdr, cmsg) \
70 	(((cmsg) == NULL) ? CMSG_FIRSTHDR(mhdr) : \
71 	(((u_char *)(cmsg) + CMSG_ALIGN((cmsg)->cmsg_len) \
72 	+ CMSG_ALIGN(sizeof(struct cmsghdr)) > \
73 	(u_char *)((mhdr)->msg_control) + (mhdr)->msg_controllen) ? \
74 	(struct cmsghdr *)NULL : \
75 	(struct cmsghdr *)((u_char *)(cmsg) + CMSG_ALIGN((cmsg)->cmsg_len))))
76 #define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+CMSG_ALIGN(len))
77 
78 #endif
79 
80 /*
81  * unify WSAGetLastError() with errno.
82  *
83  * and convert int <-> SOCKET.
84  */
85 
86 /* int <-> socket */
87 #define FD2S(fd) ((intptr_t)(fd))
88 #define S2FD(fd) ((int)(fd))
89 
90 /* socket <-> HANDLE, plain casts */
91 #define FD2H(fd) ((HANDLE)FD2S(fd))
92 #define H2FD(h) S2FD((SOCKET)(h))
93 
ewrap(int res)94 static inline int ewrap(int res) {
95 	if (res < 0)
96 		errno = WSAGetLastError();
97 	return res;
98 }
99 
100 /* proper signature for setsockopt */
w_setsockopt(int fd,int level,int optname,const void * optval,int optlen)101 static inline int w_setsockopt(int fd, int level, int optname, const void *optval, int optlen)
102 {
103 	return ewrap(setsockopt(FD2S(fd), level, optname, optval, optlen));
104 }
105 #define setsockopt(a,b,c,d,e) w_setsockopt(a,b,c,d,e)
106 
107 /* proper signature for send */
w_send(int fd,const void * buf,size_t len,int flags)108 static inline ssize_t w_send(int fd, const void *buf, size_t len, int flags) {
109 	return ewrap(send(FD2S(fd), buf, len, flags));
110 }
111 #define send(a,b,c,d) w_send(a,b,c,d)
112 
113 /* proper signature for recv */
w_recv(int fd,void * buf,size_t len,int flags)114 static inline ssize_t w_recv(int fd, void *buf, size_t len, int flags) {
115 	return ewrap(recv(FD2S(fd), buf, len, flags));
116 }
117 #define recv(a,b,c,d) w_recv(a,b,c,d)
118 
119 #define getsockopt(a,b,c,d,e) ewrap(getsockopt(FD2S(a),b,c,d,e))
120 #define connect(a,b,c) ewrap(connect(FD2S(a),b,c))
121 #define socket(a,b,c) ewrap(S2FD(socket(a,b,c)))
122 #define bind(a,b,c) ewrap(bind(FD2S(a),b,c))
123 #define listen(a,b) ewrap(listen(FD2S(a),b))
124 #define accept(a,b,c) ewrap(accept(FD2S(a),b,c))
125 #define getpeername(a,b,c) ewrap(getpeername(FD2S(a),b,c))
126 #define getsockname(a,b,c) ewrap(getsockname(FD2S(a),b,c))
127 #define select(a,b,c,d,e) ewrap(select(a,b,c,d,e))
128 
w_gethostbyname(const char * n)129 static inline struct hostent *w_gethostbyname(const char *n) {
130 	struct hostent *res = gethostbyname(n);
131 	if (!res) errno = WSAGetLastError();
132 	return res;
133 }
134 #define gethostbyname(a) w_gethostbyname(a)
135 
136 
137 /* make unix socket related code compile */
138 struct sockaddr_un {
139 	short sun_family;
140 	char sun_path[128];
141 };
142 
143 /* sendmsg is not used */
sendmsg(int s,const struct msghdr * m,int flags)144 static inline int sendmsg(int s, const struct msghdr *m, int flags)
145 {
146 	if (m->msg_iovlen != 1) {
147 		errno = EINVAL;
148 		return -1;
149 	}
150 	return send(s, m->msg_iov[0].iov_base,
151 		    m->msg_iov[0].iov_len, flags);
152 }
153 
154 /* recvmsg() is, but only with one iov */
recvmsg(int s,struct msghdr * m,int flags)155 static inline int recvmsg(int s, struct msghdr *m, int flags)
156 {
157 	if (m->msg_iovlen != 1) {
158 		errno = EINVAL;
159 		return -1;
160 	}
161 	if (m->msg_controllen)
162 		m->msg_controllen = 0;
163 	return recv(s, m->msg_iov[0].iov_base,
164 		    m->msg_iov[0].iov_len, flags);
165 }
166 
167 /*
168  * fcntl
169  */
170 
171 #define F_GETFD 1
172 #define F_SETFD 2
173 #define F_GETFL 3
174 #define F_SETFL 4
175 #define O_NONBLOCK 1
176 #define FD_CLOEXEC HANDLE_FLAG_INHERIT
177 
fcntl(int fd,int cmd,long arg)178 static inline int fcntl(int fd, int cmd, long arg)
179 {
180 	ULONG lval;
181 	DWORD dval;
182 	switch (cmd) {
183 	case F_GETFD:
184 		if (GetHandleInformation(FD2H(fd), &dval))
185 			return dval;
186 		errno = EINVAL;
187 		return -1;
188 	case F_SETFD:
189 		/* set FD_CLOEXEC */
190 		if (SetHandleInformation(FD2H(fd), FD_CLOEXEC, arg))
191 			return 0;
192 		errno = EINVAL;
193 		return -1;
194 	case F_GETFL:
195 		/* O_NONBLOCK? */
196 		return 0;
197 	case F_SETFL:
198 		/* set O_NONBLOCK */
199 		lval = (arg & O_NONBLOCK) ? 1 : 0;
200 		if (ioctlsocket(FD2S(fd), FIONBIO, &lval) == SOCKET_ERROR) {
201 			errno = WSAGetLastError();
202 			return -1;
203 		}
204 		return 0;
205 	default:
206 		errno = EINVAL;
207 		return -1;
208 	}
209 }
210 
211 /*
212  * SIO_KEEPALIVE_VALS for mingw32
213  */
214 
215 #if !defined(SIO_KEEPALIVE_VALS)
216 #define SIO_KEEPALIVE_VALS	_WSAIOW(IOC_VENDOR,4)
217 struct tcp_keepalive {
218 	u_long onoff;
219 	u_long keepalivetime;
220 	u_long keepaliveinterval;
221 };
222 #endif
223 
224 /*
225  * Use native poll() if available
226  */
227 
228 #if !defined(HAVE_POLL) && defined(POLLIN)
229 
230 #define HAVE_POLL
231 #define poll(a,b,c) usual_poll(a,b,c)
232 
poll(struct pollfd * fds,int nfds,int timeout)233 static inline int poll(struct pollfd *fds, int nfds, int timeout)
234 {
235 	return WSAPoll(fds, nfds, timeout);
236 }
237 
238 #endif
239 
240 #endif
241