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