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