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