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