]> git.meshlink.io Git - catta/blob - src/compat/windows/wincompat.h
fix headers to be used with Visual Studio 2015 RC
[catta] / src / compat / windows / wincompat.h
1 #ifndef foowincompatfoo
2 #define foowincompatfoo
3
4 // This file and its companion wincompat.c provide some Posix interfaces to
5 // Windows APIs so the rest of the code can keep using them.
6
7
8 // require at least Windows Vista
9 #undef WINVER
10 #undef _WIN32_WINNT
11 #define WINVER 0x0600
12 #define _WIN32_WINNT WINVER
13
14 #include <winsock2.h>
15 #include <ws2tcpip.h>
16 #include <mswsock.h>
17 #include <sys/types.h>
18
19 // TODO: fix mingw32 x86 or drop support and use x86_x64
20 // copied from x86_64-4.8.3-release-posix-seh-rt_v3-rev0 for mingw32 x86 4.8.1
21 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
22   // from winsock2.h
23   #define POLLRDNORM 0x0100
24   #define POLLRDBAND 0x0200
25   #define POLLIN    (POLLRDNORM | POLLRDBAND)
26   #define POLLPRI    0x0400
27
28   #define POLLWRNORM 0x0010
29   #define POLLOUT   (POLLWRNORM)
30   #define POLLWRBAND 0x0020
31
32   #define POLLERR    0x0001
33   #define POLLHUP    0x0002
34   #define POLLNVAL   0x0004
35
36   typedef struct pollfd {
37     SOCKET fd;
38     short  events;
39     short  revents;
40   } WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
41
42   // to fix redefenition of 'timespec' defined in pthread.h and parts/time.h used by simple-watch.c
43   #define HAVE_STRUCT_TIMESPEC
44
45   // from ws2ipdef.h
46   #define IPV6_HOPOPTS           1
47   #define IPV6_HDRINCL           2
48   #define IPV6_UNICAST_HOPS      4
49   #define IPV6_MULTICAST_IF      9
50   #define IPV6_MULTICAST_HOPS    10
51   #define IPV6_MULTICAST_LOOP    11
52   #define IPV6_ADD_MEMBERSHIP    12
53   #define IPV6_JOIN_GROUP        IPV6_ADD_MEMBERSHIP
54   #define IPV6_DROP_MEMBERSHIP   13
55   #define IPV6_LEAVE_GROUP       IPV6_DROP_MEMBERSHIP
56   #define IPV6_DONTFRAG          14
57   #define IPV6_PKTINFO           19
58   #define IPV6_HOPLIMIT          21
59   #define IPV6_PROTECTION_LEVEL  23
60   #define IPV6_RECVIF            24
61   #define IPV6_RECVDSTADDR       25
62   #define IPV6_CHECKSUM          26
63   #define IPV6_V6ONLY            27
64   #define IPV6_IFLIST            28
65   #define IPV6_ADD_IFLIST        29
66   #define IPV6_DEL_IFLIST        30
67   #define IPV6_UNICAST_IF        31
68   #define IPV6_RTHDR             32
69   #define IPV6_RECVRTHDR         38
70   #define IPV6_TCLASS            39
71   #define IPV6_RECVTCLASS        40
72
73   // from errno.h
74   #ifndef EADDRINUSE
75   #define EADDRINUSE 100
76   #endif
77
78   #ifndef EWOULDBLOCK
79   #define EWOULDBLOCK 140
80   #endif
81
82   // from mswsock.h
83   #define MSG_TRUNC 0x0100
84   #define MSG_CTRUNC 0x0200
85
86   // from netioapi.h
87   //.... lots of dependencies x-(
88   // TODO: fix mingw32 x86 or drop support and use x86_x64
89 #endif
90
91
92 // wrappers around WSAStartup/WSACleanup to avoid clutter
93 void winsock_init(void);
94 void winsock_exit(void);
95
96
97 // the equivalent of strerror(errno) for Windows sockets
98 char *errnostrsocket(void);
99
100
101 // Winsock doesn't have recvmsg/sendmsg but offers the same functionality
102 // with WSARecvMsg/WSASendMsg, so we implement the former in terms of the
103 // latter.
104
105 struct iovec {                   /* Scatter/gather array items */
106    void  *iov_base;              /* Starting address */
107    size_t iov_len;               /* Number of bytes to transfer */
108 };
109
110 struct msghdr {
111    void         *msg_name;       /* optional address */
112    socklen_t     msg_namelen;    /* size of address */
113    struct iovec *msg_iov;        /* scatter/gather array */
114    size_t        msg_iovlen;     /* # elements in msg_iov */
115    void         *msg_control;    /* ancillary data, see below */
116    size_t        msg_controllen; /* ancillary data buffer len */
117    int           msg_flags;      /* flags on received message */
118 };
119
120 // MSDN says this struct is called wsacmsghdr but MingW uses _WSACMSGHDR.
121 // TODO: Verify what it is on actual Windows.
122 // cf. http://msdn.microsoft.com/en-us/library/ms741645(v=vs.85).aspx
123 // -->
124 // MingW32 x86 4.8.1 uses wsacmsghdr, MingW x86_x64 uses _WSACMSGHDR and Visual Studio 2015 RC (ws2def.h) defines:
125 // #if(_WIN32_WINNT >= 0x0600)
126 // #define _WSACMSGHDR cmsghdr
127 // #endif //(_WIN32_WINNT>=0x0600)
128 // typedef struct _WSACMSGHDR {
129 //     SIZE_T      cmsg_len;
130 //     INT         cmsg_level;
131 //     INT         cmsg_type;
132 //     /* followed by UCHAR cmsg_data[] */
133 // } WSACMSGHDR, *PWSACMSGHDR, FAR *LPWSACMSGHDR;
134 #ifdef __MINGW32__
135   #ifdef __MINGW64_VERSION_MAJOR
136     #define cmsghdr _WSACMSGHDR     // as in 'struct cmsghdr'
137   #else
138     #define cmsghdr wsacmsghdr      // as in 'struct cmsghdr'
139   #endif
140 #elif (_WIN32_WINNT < 0x0600)
141   #define cmsghdr _WSACMSGHDR
142 #endif
143
144 // VS2015 ws2def.h already defines: #define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
145 #ifdef CMSG_FIRSTHDR
146 #undef CMSG_FIRSTHDR
147 #endif
148 static inline struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *m) {
149     WSAMSG wm;
150     wm.Control.len = m->msg_controllen;
151     wm.Control.buf = (char*)m->msg_control;
152     return WSA_CMSG_FIRSTHDR(&wm);
153 }
154
155 // VS2015 ws2def.h already defines: #define CMSG_NXTHDR WSA_CMSG_NXTHDR
156 #ifdef CMSG_NXTHDR
157 #undef CMSG_NXTHDR
158 #endif
159 static inline struct cmsghdr *CMSG_NXTHDR(struct msghdr *m, struct cmsghdr *c) {
160     WSAMSG wm;
161     wm.Control.len = m->msg_controllen;
162     wm.Control.buf = (char*)m->msg_control;
163     return WSA_CMSG_NXTHDR(&wm, c);
164 }
165
166 #ifndef CMSG_SPACE
167  #define CMSG_SPACE(len) WSA_CMSG_SPACE(len)
168 #endif
169 #ifndef CMSG_LEN
170  #define CMSG_LEN(len) WSA_CMSG_LEN(len)
171 #endif
172
173 // we're going to be naughty and redefine CMSG_DATA as an alias even though it
174 // is also a constant defined in wincrypt.h which we don't care about.
175 #undef CMSG_DATA
176 #define CMSG_DATA(c) WSA_CMSG_DATA(c)
177
178 // VS2012 and up has no ssize_t defined, before it was defined as unsigned int
179 #ifndef _SSIZE_T
180 #define _SSIZE_T
181 typedef signed int        ssize_t;
182 #endif
183
184 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
185 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
186
187 // ESHUTDOWN does not seem to exist on Windows, even though WSAESHUTDOWN does.
188 // MingW doesn't define it and MSDN doesn't list it, so we alias it to EBADF.
189 // cf. http://msdn.microsoft.com/en-us/library/5814770t.aspx
190 #ifndef ESHUTDOWN
191 #define ESHUTDOWN EBADF
192 #endif
193
194
195 // Windows doesn't have ioctl but offers ioctlsocket for some socket-related
196 // functions. Unfortunately, argument types differ, so we implement a
197 // (restricted) wrapper.
198 int ioctl(int d, unsigned long request, int *p);
199
200
201 // Windows lacks poll, but WSAPoll is good enough for us.
202 #define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
203
204 // Windows lacks pipe. It has an equivalent CreatePipe but we really need
205 // something to give to WSAPoll, so we fake it with a local TCP socket. (ugh)
206 int pipe(int pipefd[2]);
207
208 // pipe(socket)-specific read/write/close equivalents
209 #define closepipe closesocket
210 #define writepipe(s,buf,len) send(s, buf, len, 0)
211 #define readpipe(s,buf,len) recv(s, buf, len, 0)
212
213
214 // Windows logically doesn't have uname, so we supply a replacement.
215
216 struct utsname {
217    char sysname[9];    /* Operating system name (e.g., "Linux") */
218    char nodename[MAX_COMPUTERNAME_LENGTH+1];
219                        /* Name within "some implementation-defined network" */
220    char release[9];    /* Operating system release (e.g., "2.6.28") */
221    char version[9];    /* Operating system version */
222    char machine[9];    /* Hardware identifier */
223 };
224
225 int uname(struct utsname *buf);
226
227
228 #endif