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_HPP
9 #define BABELTRACE_COMPAT_SOCKET_HPP
15 # include <winsock2.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
27 static inline int bt_socket_init(int log_level BT_SOCKET_LOG_LEVEL_UNUSED_ATTR)
33 /* Request winsock 2.2 support */
34 verreq = MAKEWORD(2, 2);
36 ret = WSAStartup(verreq, &wsa);
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);
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");
58 static inline int bt_socket_fini(void)
63 static inline int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
65 return send(sockfd, (const char *) buf, len, flags);
68 static inline int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
70 return recv(sockfd, (char *) buf, len, flags);
73 static inline int bt_socket_close(int fd)
75 return closesocket(fd);
78 static inline bool bt_socket_interrupted(void)
80 /* There is no equivalent to EINTR in winsock 2.2 */
84 static inline const char *bt_socket_errormsg(void)
87 int error = WSAGetLastError();
91 errstr = "Call interrupted";
97 errstr = "Bad access";
100 errstr = "Bad argument";
103 errstr = "Invalid arguments";
106 errstr = "Out of file descriptors";
109 errstr = "Call would block";
113 errstr = "Blocking call in progress";
116 errstr = "Descriptor is not a socket";
118 case WSAEDESTADDRREQ:
119 errstr = "Need destination address";
122 errstr = "Bad message size";
125 errstr = "Bad protocol";
128 errstr = "Protocol option is unsupported";
130 case WSAEPROTONOSUPPORT:
131 errstr = "Protocol is unsupported";
133 case WSAESOCKTNOSUPPORT:
134 errstr = "Socket is unsupported";
137 errstr = "Operation not supported";
139 case WSAEAFNOSUPPORT:
140 errstr = "Address family not supported";
142 case WSAEPFNOSUPPORT:
143 errstr = "Protocol family not supported";
146 errstr = "Address already in use";
148 case WSAEADDRNOTAVAIL:
149 errstr = "Address not available";
152 errstr = "Network down";
155 errstr = "Network unreachable";
158 errstr = "Network has been reset";
160 case WSAECONNABORTED:
161 errstr = "Connection was aborted";
164 errstr = "Connection was reset";
167 errstr = "No buffer space";
170 errstr = "Socket is already connected";
173 errstr = "Socket is not connected";
176 errstr = "Socket has been shut down";
178 case WSAETOOMANYREFS:
179 errstr = "Too many references";
182 errstr = "Timed out";
184 case WSAECONNREFUSED:
185 errstr = "Connection refused";
190 case WSAENAMETOOLONG:
191 errstr = "Name too long";
194 errstr = "Host down";
196 case WSAEHOSTUNREACH:
197 errstr = "Host unreachable";
200 errstr = "Not empty";
203 errstr = "Process limit reached";
206 errstr = "Too many users";
209 errstr = "Bad quota";
212 errstr = "Something is stale";
215 errstr = "Remote error";
218 errstr = "Disconnected";
221 /* Extended Winsock errors */
223 errstr = "Winsock library is not ready";
225 case WSANOTINITIALISED:
226 errstr = "Winsock library not initialised";
228 case WSAVERNOTSUPPORTED:
229 errstr = "Winsock version not supported";
232 /* getXbyY() errors (already handled in herrmsg):
233 * Authoritative Answer: Host not found */
234 case WSAHOST_NOT_FOUND:
235 errstr = "Host not found";
238 /* Non-Authoritative: Host not found, or SERVERFAIL */
240 errstr = "Host not found, try again";
243 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
245 errstr = "Unrecoverable error in call to nameserver";
248 /* Valid name, no data record of requested type */
250 errstr = "No data record of requested type";
254 errstr = "Unknown error";
260 #else /* __MINGW32__ */
265 # include <netinet/in.h>
266 # include <sys/socket.h>
269 # define BT_INVALID_SOCKET -1
270 # define BT_SOCKET_ERROR -1
271 # define BT_SOCKET int
273 static inline int bt_socket_init(int log_level __attribute__((unused)))
278 static inline int bt_socket_fini(void)
283 static inline int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
285 return send(sockfd, buf, len, flags);
288 static inline int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
290 return recv(sockfd, buf, len, flags);
293 static inline int bt_socket_close(int fd)
298 static inline bool bt_socket_interrupted(void)
300 return (errno == EINTR);
303 static inline const char *bt_socket_errormsg(void)
305 return g_strerror(errno);
310 * This wrapper is used on platforms that have no way of ignoring SIGPIPE
316 # define MSG_NOSIGNAL SO_NOSIGPIPE
317 # elif defined(__MINGW32__)
318 # define MSG_NOSIGNAL 0
322 #if defined(MSG_NOSIGNAL)
323 static inline ssize_t bt_socket_send_nosigpipe(int fd, const void *buffer, size_t size)
325 return bt_socket_send(fd, buffer, size, MSG_NOSIGNAL);
331 static inline ssize_t bt_socket_send_nosigpipe(int fd, const void *buffer, size_t size)
335 sigset_t sigpipe_set, pending_set, old_set;
336 int sigpipe_was_pending;
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.
344 if (sigemptyset(&pending_set)) {
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.
352 if (sigpending(&pending_set)) {
355 sigpipe_was_pending = sigismember(&pending_set, SIGPIPE);
357 * If sigpipe was pending, it means it was already blocked, so
358 * no need to block it.
360 if (!sigpipe_was_pending) {
361 if (sigemptyset(&sigpipe_set)) {
364 if (sigaddset(&sigpipe_set, SIGPIPE)) {
367 if (pthread_sigmask(SIG_BLOCK, &sigpipe_set, &old_set)) {
372 /* Send and save errno. */
373 sent = bt_socket_send(fd, buffer, size, 0);
376 if (sent == -1 && errno == EPIPE && !sigpipe_was_pending) {
377 struct timespec timeout = {0, 0};
381 ret = sigtimedwait(&sigpipe_set, NULL, &timeout);
382 } while (ret == -1 && errno == EINTR);
384 if (!sigpipe_was_pending) {
385 if (pthread_sigmask(SIG_SETMASK, &old_set, NULL)) {
389 /* Restore send() errno */
396 #endif /* BABELTRACE_COMPAT_SOCKET_HPP */