Port: Add winsock support to live for mingw
[babeltrace.git] / include / babeltrace / compat / socket-internal.h
CommitLineData
1cb3cdd7
MJ
1#ifndef _BABELTRACE_COMPAT_SOCKET_H
2#define _BABELTRACE_COMPAT_SOCKET_H
3
4/*
5 * babeltrace/compat/socket.h
6 *
7 * Copyright (C) 2015-2017 Michael Jeanson <mjeanson@efficios.com>
8 * 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29#ifdef __MINGW32__
30
31#include <winsock2.h>
32
33#define BT_INVALID_SOCKET INVALID_SOCKET
34#define BT_SOCKET_ERROR SOCKET_ERROR
35#define BT_SOCKET SOCKET
36
37static inline
38int bt_socket_init(void)
39{
40 WORD verreq;
41 WSADATA wsa;
42 int ret;
43
44 /* Request winsock 2.2 support */
45 verreq = MAKEWORD(2, 2);
46
47 ret = WSAStartup(verreq, &wsa);
48 if (ret != 0) {
49 BT_LOGE("Winsock init failed with error: %d", ret);
50 goto end;
51 }
52
53 if (LOBYTE(wsa.wVersion) != 2 || HIBYTE(wsa.wVersion) != 2) {
54 BT_LOGE_STR("Could not init winsock 2.2 support");
55 WSACleanup();
56 ret = -1;
57 }
58
59end:
60 return ret;
61}
62
63static inline
64int bt_socket_fini(void)
65{
66 return WSACleanup();
67}
68
69static inline
70int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
71{
72 return send(sockfd, buf, len, flags);
73}
74
75static inline
76int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
77{
78 return recv(sockfd, buf, len, flags);
79}
80
81static inline
82int bt_socket_close(int fd)
83{
84 return closesocket(fd);
85}
86
87static inline
88bool bt_socket_interrupted(void)
89{
90 /* There is no equivalent to EINTR in winsock 2.2 */
91 return false;
92}
93
94static inline
95const char *bt_socket_errormsg(void)
96{
97 const char *errstr;
98 int error = WSAGetLastError();
99
100 switch (error) {
101 case WSAEINTR:
102 errstr = "Call interrupted";
103 break;
104 case WSAEBADF:
105 errstr = "Bad file";
106 break;
107 case WSAEACCES:
108 errstr = "Bad access";
109 break;
110 case WSAEFAULT:
111 errstr = "Bad argument";
112 break;
113 case WSAEINVAL:
114 errstr = "Invalid arguments";
115 break;
116 case WSAEMFILE:
117 errstr = "Out of file descriptors";
118 break;
119 case WSAEWOULDBLOCK:
120 errstr = "Call would block";
121 break;
122 case WSAEINPROGRESS:
123 case WSAEALREADY:
124 errstr = "Blocking call in progress";
125 break;
126 case WSAENOTSOCK:
127 errstr = "Descriptor is not a socket";
128 break;
129 case WSAEDESTADDRREQ:
130 errstr = "Need destination address";
131 break;
132 case WSAEMSGSIZE:
133 errstr = "Bad message size";
134 break;
135 case WSAEPROTOTYPE:
136 errstr = "Bad protocol";
137 break;
138 case WSAENOPROTOOPT:
139 errstr = "Protocol option is unsupported";
140 break;
141 case WSAEPROTONOSUPPORT:
142 errstr = "Protocol is unsupported";
143 break;
144 case WSAESOCKTNOSUPPORT:
145 errstr = "Socket is unsupported";
146 break;
147 case WSAEOPNOTSUPP:
148 errstr = "Operation not supported";
149 break;
150 case WSAEAFNOSUPPORT:
151 errstr = "Address family not supported";
152 break;
153 case WSAEPFNOSUPPORT:
154 errstr = "Protocol family not supported";
155 break;
156 case WSAEADDRINUSE:
157 errstr = "Address already in use";
158 break;
159 case WSAEADDRNOTAVAIL:
160 errstr = "Address not available";
161 break;
162 case WSAENETDOWN:
163 errstr = "Network down";
164 break;
165 case WSAENETUNREACH:
166 errstr = "Network unreachable";
167 break;
168 case WSAENETRESET:
169 errstr = "Network has been reset";
170 break;
171 case WSAECONNABORTED:
172 errstr = "Connection was aborted";
173 break;
174 case WSAECONNRESET:
175 errstr = "Connection was reset";
176 break;
177 case WSAENOBUFS:
178 errstr = "No buffer space";
179 break;
180 case WSAEISCONN:
181 errstr = "Socket is already connected";
182 break;
183 case WSAENOTCONN:
184 errstr = "Socket is not connected";
185 break;
186 case WSAESHUTDOWN:
187 errstr = "Socket has been shut down";
188 break;
189 case WSAETOOMANYREFS:
190 errstr = "Too many references";
191 break;
192 case WSAETIMEDOUT:
193 errstr = "Timed out";
194 break;
195 case WSAECONNREFUSED:
196 errstr = "Connection refused";
197 break;
198 case WSAELOOP:
199 errstr = "Loop??";
200 break;
201 case WSAENAMETOOLONG:
202 errstr = "Name too long";
203 break;
204 case WSAEHOSTDOWN:
205 errstr = "Host down";
206 break;
207 case WSAEHOSTUNREACH:
208 errstr = "Host unreachable";
209 break;
210 case WSAENOTEMPTY:
211 errstr = "Not empty";
212 break;
213 case WSAEPROCLIM:
214 errstr = "Process limit reached";
215 break;
216 case WSAEUSERS:
217 errstr = "Too many users";
218 break;
219 case WSAEDQUOT:
220 errstr = "Bad quota";
221 break;
222 case WSAESTALE:
223 errstr = "Something is stale";
224 break;
225 case WSAEREMOTE:
226 errstr = "Remote error";
227 break;
228 case WSAEDISCON:
229 errstr = "Disconnected";
230 break;
231
232 /* Extended Winsock errors */
233 case WSASYSNOTREADY:
234 errstr = "Winsock library is not ready";
235 break;
236 case WSANOTINITIALISED:
237 errstr = "Winsock library not initialised";
238 break;
239 case WSAVERNOTSUPPORTED:
240 errstr = "Winsock version not supported";
241 break;
242
243 /* getXbyY() errors (already handled in herrmsg):
244 * Authoritative Answer: Host not found */
245 case WSAHOST_NOT_FOUND:
246 errstr = "Host not found";
247 break;
248
249 /* Non-Authoritative: Host not found, or SERVERFAIL */
250 case WSATRY_AGAIN:
251 errstr = "Host not found, try again";
252 break;
253
254 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
255 case WSANO_RECOVERY:
256 errstr = "Unrecoverable error in call to nameserver";
257 break;
258
259 /* Valid name, no data record of requested type */
260 case WSANO_DATA:
261 errstr = "No data record of requested type";
262 break;
263
264 default:
265 errstr = "Unknown error";
266 }
267
268 return errstr;
269}
270
271#else /* __MINGW32__ */
272
273#include <unistd.h>
274#include <sys/socket.h>
275#include <netinet/in.h>
276#include <netdb.h>
277
278#define BT_INVALID_SOCKET -1
279#define BT_SOCKET_ERROR -1
280#define BT_SOCKET int
281
282static inline
283int bt_socket_init(void)
284{
285 return 0;
286}
287
288static inline
289int bt_socket_fini(void)
290{
291 return 0;
292}
293
294static inline
295int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
296{
297 return send(sockfd, buf, len, flags);
298}
299
300static inline
301int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
302{
303 return recv(sockfd, buf, len, flags);
304}
305
306static inline
307int bt_socket_close(int fd)
308{
309 return close(fd);
310}
311
312static inline
313bool bt_socket_interrupted(void)
314{
315 return (errno == EINTR);
316}
317
318static inline
319const char *bt_socket_errormsg(void)
320{
321 return g_strerror(errno);
322}
323#endif
324
325
326/*
327 * This wrapper is used on platforms that have no way of ignoring SIGPIPE
328 * during a send().
329 */
330
331#ifndef MSG_NOSIGNAL
332# ifdef SO_NOSIGPIPE
333# define MSG_NOSIGNAL SO_NOSIGPIPE
334# elif defined(__MINGW32__)
335# define MSG_NOSIGNAL 0
336# endif
337#endif
338
339#if defined(MSG_NOSIGNAL)
340static inline
341ssize_t bt_socket_send_nosigpipe(int fd, const void *buffer, size_t size)
342{
343 return bt_socket_send(fd, buffer, size, MSG_NOSIGNAL);
344}
345#else
346
347#include <signal.h>
348
349static inline
350ssize_t bt_socket_send_nosigpipe(int fd, const void *buffer, size_t size)
351{
352 ssize_t sent;
353 int saved_err;
354 sigset_t sigpipe_set, pending_set, old_set;
355 int sigpipe_was_pending;
356
357 /*
358 * Discard the SIGPIPE from send(), not disturbing any SIGPIPE
359 * that might be already pending. If a bogus SIGPIPE is sent to
360 * the entire process concurrently by a malicious user, it may
361 * be simply discarded.
362 */
363 if (sigemptyset(&pending_set)) {
364 return -1;
365 }
366 /*
367 * sigpending returns the mask of signals that are _both_
368 * blocked for the thread _and_ pending for either the thread or
369 * the entire process.
370 */
371 if (sigpending(&pending_set)) {
372 return -1;
373 }
374 sigpipe_was_pending = sigismember(&pending_set, SIGPIPE);
375 /*
376 * If sigpipe was pending, it means it was already blocked, so
377 * no need to block it.
378 */
379 if (!sigpipe_was_pending) {
380 if (sigemptyset(&sigpipe_set)) {
381 return -1;
382 }
383 if (sigaddset(&sigpipe_set, SIGPIPE)) {
384 return -1;
385 }
386 if (pthread_sigmask(SIG_BLOCK, &sigpipe_set, &old_set)) {
387 return -1;
388 }
389 }
390
391 /* Send and save errno. */
392 sent = bt_socket_send(fd, buffer, size, 0);
393 saved_err = errno;
394
395 if (sent == -1 && errno == EPIPE && !sigpipe_was_pending) {
396 struct timespec timeout = { 0, 0 };
397 int ret;
398
399 do {
400 ret = sigtimedwait(&sigpipe_set, NULL,
401 &timeout);
402 } while (ret == -1 && errno == EINTR);
403 }
404 if (!sigpipe_was_pending) {
405 if (pthread_sigmask(SIG_SETMASK, &old_set, NULL)) {
406 return -1;
407 }
408 }
409 /* Restore send() errno */
410 errno = saved_err;
411
412 return sent;
413}
414#endif
415
416
417#endif /* _BABELTRACE_COMPAT_SOCKET_H */
This page took 0.037601 seconds and 4 git commands to generate.