2 * SPDX-License-Identifier: MIT
4 * Copyright (C) 2015-2017 Michael Jeanson <mjeanson@efficios.com>
5 * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 #ifndef _BABELTRACE_COMPAT_SOCKET_H
9 #define _BABELTRACE_COMPAT_SOCKET_H
17 #define BT_INVALID_SOCKET INVALID_SOCKET
18 #define BT_SOCKET_ERROR SOCKET_ERROR
19 #define BT_SOCKET SOCKET
21 #ifndef BT_LOG_WRITE_CUR_LVL
22 #define BT_SOCKET_LOG_LEVEL_UNUSED_ATTR __attribute__((unused))
24 #define BT_SOCKET_LOG_LEVEL_UNUSED_ATTR
28 int bt_socket_init(int log_level BT_SOCKET_LOG_LEVEL_UNUSED_ATTR
)
34 /* Request winsock 2.2 support */
35 verreq
= MAKEWORD(2, 2);
37 ret
= WSAStartup(verreq
, &wsa
);
39 #ifdef BT_LOG_WRITE_PRINTF_CUR_LVL
40 BT_LOG_WRITE_PRINTF_CUR_LVL(BT_LOG_ERROR
, log_level
, BT_LOG_TAG
,
41 "Winsock init failed with error: %d", ret
);
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");
60 int bt_socket_fini(void)
66 int bt_socket_send(int sockfd
, const void *buf
, size_t len
, int flags
)
68 return send(sockfd
, (const char *) buf
, len
, flags
);
72 int bt_socket_recv(int sockfd
, void *buf
, size_t len
, int flags
)
74 return recv(sockfd
, (char *) buf
, len
, flags
);
78 int bt_socket_close(int fd
)
80 return closesocket(fd
);
84 bool bt_socket_interrupted(void)
86 /* There is no equivalent to EINTR in winsock 2.2 */
91 const char *bt_socket_errormsg(void)
94 int error
= WSAGetLastError();
98 errstr
= "Call interrupted";
104 errstr
= "Bad access";
107 errstr
= "Bad argument";
110 errstr
= "Invalid arguments";
113 errstr
= "Out of file descriptors";
116 errstr
= "Call would block";
120 errstr
= "Blocking call in progress";
123 errstr
= "Descriptor is not a socket";
125 case WSAEDESTADDRREQ
:
126 errstr
= "Need destination address";
129 errstr
= "Bad message size";
132 errstr
= "Bad protocol";
135 errstr
= "Protocol option is unsupported";
137 case WSAEPROTONOSUPPORT
:
138 errstr
= "Protocol is unsupported";
140 case WSAESOCKTNOSUPPORT
:
141 errstr
= "Socket is unsupported";
144 errstr
= "Operation not supported";
146 case WSAEAFNOSUPPORT
:
147 errstr
= "Address family not supported";
149 case WSAEPFNOSUPPORT
:
150 errstr
= "Protocol family not supported";
153 errstr
= "Address already in use";
155 case WSAEADDRNOTAVAIL
:
156 errstr
= "Address not available";
159 errstr
= "Network down";
162 errstr
= "Network unreachable";
165 errstr
= "Network has been reset";
167 case WSAECONNABORTED
:
168 errstr
= "Connection was aborted";
171 errstr
= "Connection was reset";
174 errstr
= "No buffer space";
177 errstr
= "Socket is already connected";
180 errstr
= "Socket is not connected";
183 errstr
= "Socket has been shut down";
185 case WSAETOOMANYREFS
:
186 errstr
= "Too many references";
189 errstr
= "Timed out";
191 case WSAECONNREFUSED
:
192 errstr
= "Connection refused";
197 case WSAENAMETOOLONG
:
198 errstr
= "Name too long";
201 errstr
= "Host down";
203 case WSAEHOSTUNREACH
:
204 errstr
= "Host unreachable";
207 errstr
= "Not empty";
210 errstr
= "Process limit reached";
213 errstr
= "Too many users";
216 errstr
= "Bad quota";
219 errstr
= "Something is stale";
222 errstr
= "Remote error";
225 errstr
= "Disconnected";
228 /* Extended Winsock errors */
230 errstr
= "Winsock library is not ready";
232 case WSANOTINITIALISED
:
233 errstr
= "Winsock library not initialised";
235 case WSAVERNOTSUPPORTED
:
236 errstr
= "Winsock version not supported";
239 /* getXbyY() errors (already handled in herrmsg):
240 * Authoritative Answer: Host not found */
241 case WSAHOST_NOT_FOUND
:
242 errstr
= "Host not found";
245 /* Non-Authoritative: Host not found, or SERVERFAIL */
247 errstr
= "Host not found, try again";
250 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
252 errstr
= "Unrecoverable error in call to nameserver";
255 /* Valid name, no data record of requested type */
257 errstr
= "No data record of requested type";
261 errstr
= "Unknown error";
267 #else /* __MINGW32__ */
271 #include <netinet/in.h>
272 #include <sys/socket.h>
277 #define BT_INVALID_SOCKET -1
278 #define BT_SOCKET_ERROR -1
279 #define BT_SOCKET int
282 int bt_socket_init(int log_level
__attribute__((unused
)))
288 int bt_socket_fini(void)
294 int bt_socket_send(int sockfd
, const void *buf
, size_t len
, int flags
)
296 return send(sockfd
, buf
, len
, flags
);
300 int bt_socket_recv(int sockfd
, void *buf
, size_t len
, int flags
)
302 return recv(sockfd
, buf
, len
, flags
);
306 int bt_socket_close(int fd
)
312 bool bt_socket_interrupted(void)
314 return (errno
== EINTR
);
318 const char *bt_socket_errormsg(void)
320 return g_strerror(errno
);
326 * This wrapper is used on platforms that have no way of ignoring SIGPIPE
332 # define MSG_NOSIGNAL SO_NOSIGPIPE
333 # elif defined(__MINGW32__)
334 # define MSG_NOSIGNAL 0
338 #if defined(MSG_NOSIGNAL)
340 ssize_t
bt_socket_send_nosigpipe(int fd
, const void *buffer
, size_t size
)
342 return bt_socket_send(fd
, buffer
, size
, MSG_NOSIGNAL
);
349 ssize_t
bt_socket_send_nosigpipe(int fd
, const void *buffer
, size_t size
)
353 sigset_t sigpipe_set
, pending_set
, old_set
;
354 int sigpipe_was_pending
;
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.
362 if (sigemptyset(&pending_set
)) {
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.
370 if (sigpending(&pending_set
)) {
373 sigpipe_was_pending
= sigismember(&pending_set
, SIGPIPE
);
375 * If sigpipe was pending, it means it was already blocked, so
376 * no need to block it.
378 if (!sigpipe_was_pending
) {
379 if (sigemptyset(&sigpipe_set
)) {
382 if (sigaddset(&sigpipe_set
, SIGPIPE
)) {
385 if (pthread_sigmask(SIG_BLOCK
, &sigpipe_set
, &old_set
)) {
390 /* Send and save errno. */
391 sent
= bt_socket_send(fd
, buffer
, size
, 0);
394 if (sent
== -1 && errno
== EPIPE
&& !sigpipe_was_pending
) {
395 struct timespec timeout
= { 0, 0 };
399 ret
= sigtimedwait(&sigpipe_set
, NULL
,
401 } while (ret
== -1 && errno
== EINTR
);
403 if (!sigpipe_was_pending
) {
404 if (pthread_sigmask(SIG_SETMASK
, &old_set
, NULL
)) {
408 /* Restore send() errno */
416 #endif /* _BABELTRACE_COMPAT_SOCKET_H */