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