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
13 #include "cpp-common/bt2c/logging.hpp"
17 # include <winsock2.h>
19 # define BT_INVALID_SOCKET INVALID_SOCKET
20 # define BT_SOCKET_ERROR SOCKET_ERROR
21 # define BT_SOCKET SOCKET
23 static inline int bt_socket_init(const bt2c::Logger& logger)
29 /* Request winsock 2.2 support */
30 verreq = MAKEWORD(2, 2);
32 ret = WSAStartup(verreq, &wsa);
34 BT_CPPLOGE_SPEC(logger, "Winsock init failed with error: {}", ret);
38 if (LOBYTE(wsa.wVersion) != 2 || HIBYTE(wsa.wVersion) != 2) {
39 BT_CPPLOGE_SPEC(logger, "Could not init winsock 2.2 support");
48 static inline int bt_socket_fini(void)
53 static inline int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
55 return send(sockfd, (const char *) buf, len, flags);
58 static inline int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
60 return recv(sockfd, (char *) buf, len, flags);
63 static inline int bt_socket_close(int fd)
65 return closesocket(fd);
68 static inline bool bt_socket_interrupted(void)
70 /* There is no equivalent to EINTR in winsock 2.2 */
74 static inline const char *bt_socket_errormsg(void)
77 int error = WSAGetLastError();
81 errstr = "Call interrupted";
87 errstr = "Bad access";
90 errstr = "Bad argument";
93 errstr = "Invalid arguments";
96 errstr = "Out of file descriptors";
99 errstr = "Call would block";
103 errstr = "Blocking call in progress";
106 errstr = "Descriptor is not a socket";
108 case WSAEDESTADDRREQ:
109 errstr = "Need destination address";
112 errstr = "Bad message size";
115 errstr = "Bad protocol";
118 errstr = "Protocol option is unsupported";
120 case WSAEPROTONOSUPPORT:
121 errstr = "Protocol is unsupported";
123 case WSAESOCKTNOSUPPORT:
124 errstr = "Socket is unsupported";
127 errstr = "Operation not supported";
129 case WSAEAFNOSUPPORT:
130 errstr = "Address family not supported";
132 case WSAEPFNOSUPPORT:
133 errstr = "Protocol family not supported";
136 errstr = "Address already in use";
138 case WSAEADDRNOTAVAIL:
139 errstr = "Address not available";
142 errstr = "Network down";
145 errstr = "Network unreachable";
148 errstr = "Network has been reset";
150 case WSAECONNABORTED:
151 errstr = "Connection was aborted";
154 errstr = "Connection was reset";
157 errstr = "No buffer space";
160 errstr = "Socket is already connected";
163 errstr = "Socket is not connected";
166 errstr = "Socket has been shut down";
168 case WSAETOOMANYREFS:
169 errstr = "Too many references";
172 errstr = "Timed out";
174 case WSAECONNREFUSED:
175 errstr = "Connection refused";
180 case WSAENAMETOOLONG:
181 errstr = "Name too long";
184 errstr = "Host down";
186 case WSAEHOSTUNREACH:
187 errstr = "Host unreachable";
190 errstr = "Not empty";
193 errstr = "Process limit reached";
196 errstr = "Too many users";
199 errstr = "Bad quota";
202 errstr = "Something is stale";
205 errstr = "Remote error";
208 errstr = "Disconnected";
211 /* Extended Winsock errors */
213 errstr = "Winsock library is not ready";
215 case WSANOTINITIALISED:
216 errstr = "Winsock library not initialised";
218 case WSAVERNOTSUPPORTED:
219 errstr = "Winsock version not supported";
222 /* getXbyY() errors (already handled in herrmsg):
223 * Authoritative Answer: Host not found */
224 case WSAHOST_NOT_FOUND:
225 errstr = "Host not found";
228 /* Non-Authoritative: Host not found, or SERVERFAIL */
230 errstr = "Host not found, try again";
233 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
235 errstr = "Unrecoverable error in call to nameserver";
238 /* Valid name, no data record of requested type */
240 errstr = "No data record of requested type";
244 errstr = "Unknown error";
250 #else /* __MINGW32__ */
255 # include <netinet/in.h>
256 # include <sys/socket.h>
259 # define BT_INVALID_SOCKET -1
260 # define BT_SOCKET_ERROR -1
261 # define BT_SOCKET int
263 static inline int bt_socket_init(const bt2c::Logger&)
268 static inline int bt_socket_fini(void)
273 static inline int bt_socket_send(int sockfd, const void *buf, size_t len, int flags)
275 return send(sockfd, buf, len, flags);
278 static inline int bt_socket_recv(int sockfd, void *buf, size_t len, int flags)
280 return recv(sockfd, buf, len, flags);
283 static inline int bt_socket_close(int fd)
288 static inline bool bt_socket_interrupted(void)
290 return (errno == EINTR);
293 static inline const char *bt_socket_errormsg(void)
295 return g_strerror(errno);
300 * This wrapper is used on platforms that have no way of ignoring SIGPIPE
306 # define MSG_NOSIGNAL SO_NOSIGPIPE
307 # elif defined(__MINGW32__)
308 # define MSG_NOSIGNAL 0
312 #if defined(MSG_NOSIGNAL)
313 static inline ssize_t bt_socket_send_nosigpipe(int fd, const void *buffer, size_t size)
315 return bt_socket_send(fd, buffer, size, MSG_NOSIGNAL);
321 static inline ssize_t bt_socket_send_nosigpipe(int fd, const void *buffer, size_t size)
325 sigset_t sigpipe_set, pending_set, old_set;
326 int sigpipe_was_pending;
329 * Discard the SIGPIPE from send(), not disturbing any SIGPIPE
330 * that might be already pending. If a bogus SIGPIPE is sent to
331 * the entire process concurrently by a malicious user, it may
332 * be simply discarded.
334 if (sigemptyset(&pending_set)) {
338 * sigpending returns the mask of signals that are _both_
339 * blocked for the thread _and_ pending for either the thread or
340 * the entire process.
342 if (sigpending(&pending_set)) {
345 sigpipe_was_pending = sigismember(&pending_set, SIGPIPE);
347 * If sigpipe was pending, it means it was already blocked, so
348 * no need to block it.
350 if (!sigpipe_was_pending) {
351 if (sigemptyset(&sigpipe_set)) {
354 if (sigaddset(&sigpipe_set, SIGPIPE)) {
357 if (pthread_sigmask(SIG_BLOCK, &sigpipe_set, &old_set)) {
362 /* Send and save errno. */
363 sent = bt_socket_send(fd, buffer, size, 0);
366 if (sent == -1 && errno == EPIPE && !sigpipe_was_pending) {
367 struct timespec timeout = {0, 0};
371 ret = sigtimedwait(&sigpipe_set, NULL, &timeout);
372 } while (ret == -1 && errno == EINTR);
374 if (!sigpipe_was_pending) {
375 if (pthread_sigmask(SIG_SETMASK, &old_set, NULL)) {
379 /* Restore send() errno */
386 #endif /* BABELTRACE_COMPAT_SOCKET_HPP */