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