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