configure: re-enable '-Wunused-parameter'
[babeltrace.git] / src / compat / socket.h
CommitLineData
1cb3cdd7 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
1cb3cdd7 3 *
0235b0db
MJ
4 * Copyright (C) 2015-2017 Michael Jeanson <mjeanson@efficios.com>
5 * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
1cb3cdd7
MJ
6 */
7
0235b0db
MJ
8#ifndef _BABELTRACE_COMPAT_SOCKET_H
9#define _BABELTRACE_COMPAT_SOCKET_H
10
c4f23e30
FD
11#include <stdbool.h>
12
1cb3cdd7
MJ
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
ecd7492f
MJ
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
1cb3cdd7 27static inline
ecd7492f 28int bt_socket_init(int log_level BT_SOCKET_LOG_LEVEL_UNUSED_ATTR)
1cb3cdd7
MJ
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) {
95c324a4
JR
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);
f571b963 42#endif
1cb3cdd7
MJ
43 goto end;
44 }
45
46 if (LOBYTE(wsa.wVersion) != 2 || HIBYTE(wsa.wVersion) != 2) {
95c324a4
JR
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");
f571b963 50#endif
1cb3cdd7
MJ
51 WSACleanup();
52 ret = -1;
53 }
54
55end:
56 return ret;
57}
58
59static inline
60int bt_socket_fini(void)
61{
62 return WSACleanup();
63}
64
65static inline
66int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
67{
087cd0f5 68 return send(sockfd, (const char *) buf, len, flags);
1cb3cdd7
MJ
69}
70
71static inline
72int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
73{
087cd0f5 74 return recv(sockfd, (char *) buf, len, flags);
1cb3cdd7
MJ
75}
76
77static inline
78int bt_socket_close(int fd)
79{
80 return closesocket(fd);
81}
82
83static inline
84bool bt_socket_interrupted(void)
85{
86 /* There is no equivalent to EINTR in winsock 2.2 */
87 return false;
88}
89
90static inline
91const 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
c4f23e30 269#include <errno.h>
1cb3cdd7 270#include <netdb.h>
c4f23e30
FD
271#include <netinet/in.h>
272#include <sys/socket.h>
273#include <unistd.h>
274
275#include <glib.h>
1cb3cdd7
MJ
276
277#define BT_INVALID_SOCKET -1
278#define BT_SOCKET_ERROR -1
279#define BT_SOCKET int
280
281static inline
ecd7492f 282int bt_socket_init(int log_level __attribute__((unused)))
1cb3cdd7
MJ
283{
284 return 0;
285}
286
287static inline
288int bt_socket_fini(void)
289{
290 return 0;
291}
292
293static inline
294int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
295{
296 return send(sockfd, buf, len, flags);
297}
298
299static inline
300int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
301{
302 return recv(sockfd, buf, len, flags);
303}
304
305static inline
306int bt_socket_close(int fd)
307{
308 return close(fd);
309}
310
311static inline
312bool bt_socket_interrupted(void)
313{
314 return (errno == EINTR);
315}
316
317static inline
318const 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)
339static inline
340ssize_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
348static inline
349ssize_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.084566 seconds and 4 git commands to generate.