1 | /* |
2 | Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file |
3 | |
4 | This file is part of libzmq, the ZeroMQ core engine in C++. |
5 | |
6 | libzmq is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU Lesser General Public License (LGPL) as published |
8 | by the Free Software Foundation; either version 3 of the License, or |
9 | (at your option) any later version. |
10 | |
11 | As a special exception, the Contributors give you permission to link |
12 | this library with independent modules to produce an executable, |
13 | regardless of the license terms of these independent modules, and to |
14 | copy and distribute the resulting executable under terms of your choice, |
15 | provided that you also meet, for each linked independent module, the |
16 | terms and conditions of the license of that module. An independent |
17 | module is a module which is not derived from or based on this library. |
18 | If you modify this library, you must extend this exception to your |
19 | version of the library. |
20 | |
21 | libzmq is distributed in the hope that it will be useful, but WITHOUT |
22 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
23 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
24 | License for more details. |
25 | |
26 | You should have received a copy of the GNU Lesser General Public License |
27 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
28 | */ |
29 | |
30 | #include "precompiled.hpp" |
31 | #include "ip.hpp" |
32 | #include "err.hpp" |
33 | #include "macros.hpp" |
34 | #include "config.hpp" |
35 | #include "address.hpp" |
36 | |
37 | #if !defined ZMQ_HAVE_WINDOWS |
38 | #include <fcntl.h> |
39 | #include <sys/types.h> |
40 | #include <sys/socket.h> |
41 | #include <sys/stat.h> |
42 | #include <netdb.h> |
43 | #include <netinet/in.h> |
44 | #include <netinet/tcp.h> |
45 | #include <stdlib.h> |
46 | #include <unistd.h> |
47 | |
48 | #include <vector> |
49 | #else |
50 | #include "tcp.hpp" |
51 | #ifdef ZMQ_HAVE_IPC |
52 | #include "ipc_address.hpp" |
53 | #endif |
54 | |
55 | #include <direct.h> |
56 | #endif |
57 | |
58 | #if defined ZMQ_HAVE_OPENVMS || defined ZMQ_HAVE_VXWORKS |
59 | #include <ioctl.h> |
60 | #endif |
61 | |
62 | #if defined ZMQ_HAVE_VXWORKS |
63 | #include <unistd.h> |
64 | #include <sockLib.h> |
65 | #include <ioLib.h> |
66 | #endif |
67 | |
68 | #if defined ZMQ_HAVE_EVENTFD |
69 | #include <sys/eventfd.h> |
70 | #endif |
71 | |
72 | #if defined ZMQ_HAVE_OPENPGM |
73 | #ifdef ZMQ_HAVE_WINDOWS |
74 | #define __PGM_WININT_H__ |
75 | #endif |
76 | |
77 | #include <pgm/pgm.h> |
78 | #endif |
79 | |
80 | #ifdef __APPLE__ |
81 | #include <TargetConditionals.h> |
82 | #endif |
83 | |
84 | #ifndef ZMQ_HAVE_WINDOWS |
85 | // Acceptable temporary directory environment variables |
86 | static const char *tmp_env_vars[] = { |
87 | "TMPDIR" , "TEMPDIR" , "TMP" , |
88 | 0 // Sentinel |
89 | }; |
90 | #endif |
91 | |
92 | zmq::fd_t zmq::open_socket (int domain_, int type_, int protocol_) |
93 | { |
94 | int rc; |
95 | |
96 | // Setting this option result in sane behaviour when exec() functions |
97 | // are used. Old sockets are closed and don't block TCP ports etc. |
98 | #if defined ZMQ_HAVE_SOCK_CLOEXEC |
99 | type_ |= SOCK_CLOEXEC; |
100 | #endif |
101 | |
102 | #if defined ZMQ_HAVE_WINDOWS && defined WSA_FLAG_NO_HANDLE_INHERIT |
103 | // if supported, create socket with WSA_FLAG_NO_HANDLE_INHERIT, such that |
104 | // the race condition in making it non-inheritable later is avoided |
105 | const fd_t s = |
106 | WSASocket (domain_, type_, protocol_, NULL, 0, |
107 | WSA_FLAG_OVERLAPPED || WSA_FLAG_NO_HANDLE_INHERIT); |
108 | #else |
109 | const fd_t s = socket (domain_, type_, protocol_); |
110 | #endif |
111 | if (s == retired_fd) { |
112 | #ifdef ZMQ_HAVE_WINDOWS |
113 | errno = wsa_error_to_errno (WSAGetLastError ()); |
114 | #endif |
115 | return retired_fd; |
116 | } |
117 | |
118 | make_socket_noninheritable (s); |
119 | |
120 | // Socket is not yet connected so EINVAL is not a valid networking error |
121 | rc = zmq::set_nosigpipe (s); |
122 | errno_assert (rc == 0); |
123 | |
124 | return s; |
125 | } |
126 | |
127 | void zmq::unblock_socket (fd_t s_) |
128 | { |
129 | #if defined ZMQ_HAVE_WINDOWS |
130 | u_long nonblock = 1; |
131 | int rc = ioctlsocket (s_, FIONBIO, &nonblock); |
132 | wsa_assert (rc != SOCKET_ERROR); |
133 | #elif defined ZMQ_HAVE_OPENVMS || defined ZMQ_HAVE_VXWORKS |
134 | int nonblock = 1; |
135 | int rc = ioctl (s_, FIONBIO, &nonblock); |
136 | errno_assert (rc != -1); |
137 | #else |
138 | int flags = fcntl (s_, F_GETFL, 0); |
139 | if (flags == -1) |
140 | flags = 0; |
141 | int rc = fcntl (s_, F_SETFL, flags | O_NONBLOCK); |
142 | errno_assert (rc != -1); |
143 | #endif |
144 | } |
145 | |
146 | void zmq::enable_ipv4_mapping (fd_t s_) |
147 | { |
148 | LIBZMQ_UNUSED (s_); |
149 | |
150 | #if defined IPV6_V6ONLY && !defined ZMQ_HAVE_OPENBSD \ |
151 | && !defined ZMQ_HAVE_DRAGONFLY |
152 | #ifdef ZMQ_HAVE_WINDOWS |
153 | DWORD flag = 0; |
154 | #else |
155 | int flag = 0; |
156 | #endif |
157 | int rc = setsockopt (s_, IPPROTO_IPV6, IPV6_V6ONLY, |
158 | reinterpret_cast<char *> (&flag), sizeof (flag)); |
159 | #ifdef ZMQ_HAVE_WINDOWS |
160 | wsa_assert (rc != SOCKET_ERROR); |
161 | #else |
162 | errno_assert (rc == 0); |
163 | #endif |
164 | #endif |
165 | } |
166 | |
167 | int zmq::get_peer_ip_address (fd_t sockfd_, std::string &ip_addr_) |
168 | { |
169 | struct sockaddr_storage ss; |
170 | |
171 | zmq_socklen_t addrlen = |
172 | get_socket_address (sockfd_, socket_end_remote, &ss); |
173 | |
174 | if (addrlen == 0) { |
175 | #ifdef ZMQ_HAVE_WINDOWS |
176 | const int last_error = WSAGetLastError (); |
177 | wsa_assert (last_error != WSANOTINITIALISED && last_error != WSAEFAULT |
178 | && last_error != WSAEINPROGRESS |
179 | && last_error != WSAENOTSOCK); |
180 | #elif !defined(TARGET_OS_IPHONE) || !TARGET_OS_IPHONE |
181 | errno_assert (errno != EBADF && errno != EFAULT && errno != ENOTSOCK); |
182 | #else |
183 | errno_assert (errno != EFAULT && errno != ENOTSOCK); |
184 | #endif |
185 | return 0; |
186 | } |
187 | |
188 | char host[NI_MAXHOST]; |
189 | int rc = getnameinfo (reinterpret_cast<struct sockaddr *> (&ss), addrlen, |
190 | host, sizeof host, NULL, 0, NI_NUMERICHOST); |
191 | if (rc != 0) |
192 | return 0; |
193 | |
194 | ip_addr_ = host; |
195 | |
196 | union |
197 | { |
198 | struct sockaddr sa; |
199 | struct sockaddr_storage sa_stor; |
200 | } u; |
201 | |
202 | u.sa_stor = ss; |
203 | return static_cast<int> (u.sa.sa_family); |
204 | } |
205 | |
206 | void zmq::set_ip_type_of_service (fd_t s_, int iptos_) |
207 | { |
208 | int rc = setsockopt (s_, IPPROTO_IP, IP_TOS, |
209 | reinterpret_cast<char *> (&iptos_), sizeof (iptos_)); |
210 | |
211 | #ifdef ZMQ_HAVE_WINDOWS |
212 | wsa_assert (rc != SOCKET_ERROR); |
213 | #else |
214 | errno_assert (rc == 0); |
215 | #endif |
216 | |
217 | // Windows and Hurd do not support IPV6_TCLASS |
218 | #if !defined(ZMQ_HAVE_WINDOWS) && defined(IPV6_TCLASS) |
219 | rc = setsockopt (s_, IPPROTO_IPV6, IPV6_TCLASS, |
220 | reinterpret_cast<char *> (&iptos_), sizeof (iptos_)); |
221 | |
222 | // If IPv6 is not enabled ENOPROTOOPT will be returned on Linux and |
223 | // EINVAL on OSX |
224 | if (rc == -1) { |
225 | errno_assert (errno == ENOPROTOOPT || errno == EINVAL); |
226 | } |
227 | #endif |
228 | } |
229 | |
230 | int zmq::set_nosigpipe (fd_t s_) |
231 | { |
232 | #ifdef SO_NOSIGPIPE |
233 | // Make sure that SIGPIPE signal is not generated when writing to a |
234 | // connection that was already closed by the peer. |
235 | // As per POSIX spec, EINVAL will be returned if the socket was valid but |
236 | // the connection has been reset by the peer. Return an error so that the |
237 | // socket can be closed and the connection retried if necessary. |
238 | int set = 1; |
239 | int rc = setsockopt (s_, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int)); |
240 | if (rc != 0 && errno == EINVAL) |
241 | return -1; |
242 | errno_assert (rc == 0); |
243 | #else |
244 | LIBZMQ_UNUSED (s_); |
245 | #endif |
246 | |
247 | return 0; |
248 | } |
249 | |
250 | int zmq::bind_to_device (fd_t s_, const std::string &bound_device_) |
251 | { |
252 | #ifdef ZMQ_HAVE_SO_BINDTODEVICE |
253 | int rc = setsockopt (s_, SOL_SOCKET, SO_BINDTODEVICE, |
254 | bound_device_.c_str (), bound_device_.length ()); |
255 | if (rc != 0) { |
256 | assert_success_or_recoverable (s_, rc); |
257 | return -1; |
258 | } |
259 | return 0; |
260 | |
261 | #else |
262 | LIBZMQ_UNUSED (s_); |
263 | LIBZMQ_UNUSED (bound_device_); |
264 | |
265 | errno = ENOTSUP; |
266 | return -1; |
267 | #endif |
268 | } |
269 | |
270 | bool zmq::initialize_network () |
271 | { |
272 | #if defined ZMQ_HAVE_OPENPGM |
273 | |
274 | // Init PGM transport. Ensure threading and timer are enabled. Find PGM |
275 | // protocol ID. Note that if you want to use gettimeofday and sleep for |
276 | // openPGM timing, set environment variables PGM_TIMER to "GTOD" and |
277 | // PGM_SLEEP to "USLEEP". |
278 | pgm_error_t *pgm_error = NULL; |
279 | const bool ok = pgm_init (&pgm_error); |
280 | if (ok != TRUE) { |
281 | // Invalid parameters don't set pgm_error_t |
282 | zmq_assert (pgm_error != NULL); |
283 | if (pgm_error->domain == PGM_ERROR_DOMAIN_TIME |
284 | && (pgm_error->code == PGM_ERROR_FAILED)) { |
285 | // Failed to access RTC or HPET device. |
286 | pgm_error_free (pgm_error); |
287 | errno = EINVAL; |
288 | return false; |
289 | } |
290 | |
291 | // PGM_ERROR_DOMAIN_ENGINE: WSAStartup errors or missing WSARecvMsg. |
292 | zmq_assert (false); |
293 | } |
294 | #endif |
295 | |
296 | #ifdef ZMQ_HAVE_WINDOWS |
297 | // Intialise Windows sockets. Note that WSAStartup can be called multiple |
298 | // times given that WSACleanup will be called for each WSAStartup. |
299 | |
300 | WORD version_requested = MAKEWORD (2, 2); |
301 | WSADATA wsa_data; |
302 | int rc = WSAStartup (version_requested, &wsa_data); |
303 | zmq_assert (rc == 0); |
304 | zmq_assert (LOBYTE (wsa_data.wVersion) == 2 |
305 | && HIBYTE (wsa_data.wVersion) == 2); |
306 | #endif |
307 | |
308 | return true; |
309 | } |
310 | |
311 | void zmq::shutdown_network () |
312 | { |
313 | #ifdef ZMQ_HAVE_WINDOWS |
314 | // On Windows, uninitialise socket layer. |
315 | int rc = WSACleanup (); |
316 | wsa_assert (rc != SOCKET_ERROR); |
317 | #endif |
318 | |
319 | #if defined ZMQ_HAVE_OPENPGM |
320 | // Shut down the OpenPGM library. |
321 | if (pgm_shutdown () != TRUE) |
322 | zmq_assert (false); |
323 | #endif |
324 | } |
325 | |
326 | #if defined ZMQ_HAVE_WINDOWS |
327 | static void tune_socket (const SOCKET socket_) |
328 | { |
329 | BOOL tcp_nodelay = 1; |
330 | int rc = |
331 | setsockopt (socket_, IPPROTO_TCP, TCP_NODELAY, |
332 | reinterpret_cast<char *> (&tcp_nodelay), sizeof tcp_nodelay); |
333 | wsa_assert (rc != SOCKET_ERROR); |
334 | |
335 | zmq::tcp_tune_loopback_fast_path (socket_); |
336 | } |
337 | |
338 | static int make_fdpair_tcpip (zmq::fd_t *r_, zmq::fd_t *w_) |
339 | { |
340 | #if !defined _WIN32_WCE && !defined ZMQ_HAVE_WINDOWS_UWP |
341 | // Windows CE does not manage security attributes |
342 | SECURITY_DESCRIPTOR sd; |
343 | SECURITY_ATTRIBUTES sa; |
344 | memset (&sd, 0, sizeof sd); |
345 | memset (&sa, 0, sizeof sa); |
346 | |
347 | InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); |
348 | SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE); |
349 | |
350 | sa.nLength = sizeof (SECURITY_ATTRIBUTES); |
351 | sa.lpSecurityDescriptor = &sd; |
352 | #endif |
353 | |
354 | // This function has to be in a system-wide critical section so that |
355 | // two instances of the library don't accidentally create signaler |
356 | // crossing the process boundary. |
357 | // We'll use named event object to implement the critical section. |
358 | // Note that if the event object already exists, the CreateEvent requests |
359 | // EVENT_ALL_ACCESS access right. If this fails, we try to open |
360 | // the event object asking for SYNCHRONIZE access only. |
361 | HANDLE sync = NULL; |
362 | |
363 | // Create critical section only if using fixed signaler port |
364 | // Use problematic Event implementation for compatibility if using old port 5905. |
365 | // Otherwise use Mutex implementation. |
366 | int event_signaler_port = 5905; |
367 | |
368 | if (zmq::signaler_port == event_signaler_port) { |
369 | #if !defined _WIN32_WCE && !defined ZMQ_HAVE_WINDOWS_UWP |
370 | sync = |
371 | CreateEventW (&sa, FALSE, TRUE, L"Global\\zmq-signaler-port-sync" ); |
372 | #else |
373 | sync = |
374 | CreateEventW (NULL, FALSE, TRUE, L"Global\\zmq-signaler-port-sync" ); |
375 | #endif |
376 | if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED) |
377 | sync = OpenEventW (SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, |
378 | L"Global\\zmq-signaler-port-sync" ); |
379 | |
380 | win_assert (sync != NULL); |
381 | } else if (zmq::signaler_port != 0) { |
382 | wchar_t mutex_name[MAX_PATH]; |
383 | #ifdef __MINGW32__ |
384 | _snwprintf (mutex_name, MAX_PATH, L"Global\\zmq-signaler-port-%d" , |
385 | signaler_port); |
386 | #else |
387 | swprintf (mutex_name, MAX_PATH, L"Global\\zmq-signaler-port-%d" , |
388 | zmq::signaler_port); |
389 | #endif |
390 | |
391 | #if !defined _WIN32_WCE && !defined ZMQ_HAVE_WINDOWS_UWP |
392 | sync = CreateMutexW (&sa, FALSE, mutex_name); |
393 | #else |
394 | sync = CreateMutexW (NULL, FALSE, mutex_name); |
395 | #endif |
396 | if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED) |
397 | sync = OpenMutexW (SYNCHRONIZE, FALSE, mutex_name); |
398 | |
399 | win_assert (sync != NULL); |
400 | } |
401 | |
402 | // Windows has no 'socketpair' function. CreatePipe is no good as pipe |
403 | // handles cannot be polled on. Here we create the socketpair by hand. |
404 | *w_ = INVALID_SOCKET; |
405 | *r_ = INVALID_SOCKET; |
406 | |
407 | // Create listening socket. |
408 | SOCKET listener; |
409 | listener = zmq::open_socket (AF_INET, SOCK_STREAM, 0); |
410 | wsa_assert (listener != INVALID_SOCKET); |
411 | |
412 | // Set SO_REUSEADDR and TCP_NODELAY on listening socket. |
413 | BOOL so_reuseaddr = 1; |
414 | int rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR, |
415 | reinterpret_cast<char *> (&so_reuseaddr), |
416 | sizeof so_reuseaddr); |
417 | wsa_assert (rc != SOCKET_ERROR); |
418 | |
419 | tune_socket (listener); |
420 | |
421 | // Init sockaddr to signaler port. |
422 | struct sockaddr_in addr; |
423 | memset (&addr, 0, sizeof addr); |
424 | addr.sin_family = AF_INET; |
425 | addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
426 | addr.sin_port = htons (zmq::signaler_port); |
427 | |
428 | // Create the writer socket. |
429 | *w_ = zmq::open_socket (AF_INET, SOCK_STREAM, 0); |
430 | wsa_assert (*w_ != INVALID_SOCKET); |
431 | |
432 | if (sync != NULL) { |
433 | // Enter the critical section. |
434 | DWORD dwrc = WaitForSingleObject (sync, INFINITE); |
435 | zmq_assert (dwrc == WAIT_OBJECT_0 || dwrc == WAIT_ABANDONED); |
436 | } |
437 | |
438 | // Bind listening socket to signaler port. |
439 | rc = bind (listener, reinterpret_cast<const struct sockaddr *> (&addr), |
440 | sizeof addr); |
441 | |
442 | if (rc != SOCKET_ERROR && zmq::signaler_port == 0) { |
443 | // Retrieve ephemeral port number |
444 | int addrlen = sizeof addr; |
445 | rc = getsockname (listener, reinterpret_cast<struct sockaddr *> (&addr), |
446 | &addrlen); |
447 | } |
448 | |
449 | // Listen for incoming connections. |
450 | if (rc != SOCKET_ERROR) { |
451 | rc = listen (listener, 1); |
452 | } |
453 | |
454 | // Connect writer to the listener. |
455 | if (rc != SOCKET_ERROR) { |
456 | rc = connect (*w_, reinterpret_cast<struct sockaddr *> (&addr), |
457 | sizeof addr); |
458 | } |
459 | |
460 | // Accept connection from writer. |
461 | if (rc != SOCKET_ERROR) { |
462 | // Set TCP_NODELAY on writer socket. |
463 | tune_socket (*w_); |
464 | |
465 | *r_ = accept (listener, NULL, NULL); |
466 | } |
467 | |
468 | // Send/receive large chunk to work around TCP slow start |
469 | // This code is a workaround for #1608 |
470 | if (*r_ != INVALID_SOCKET) { |
471 | size_t dummy_size = |
472 | 1024 * 1024; // 1M to overload default receive buffer |
473 | unsigned char *dummy = |
474 | static_cast<unsigned char *> (malloc (dummy_size)); |
475 | wsa_assert (dummy); |
476 | |
477 | int still_to_send = static_cast<int> (dummy_size); |
478 | int still_to_recv = static_cast<int> (dummy_size); |
479 | while (still_to_send || still_to_recv) { |
480 | int nbytes; |
481 | if (still_to_send > 0) { |
482 | nbytes = ::send ( |
483 | *w_, |
484 | reinterpret_cast<char *> (dummy + dummy_size - still_to_send), |
485 | still_to_send, 0); |
486 | wsa_assert (nbytes != SOCKET_ERROR); |
487 | still_to_send -= nbytes; |
488 | } |
489 | nbytes = ::recv ( |
490 | *r_, |
491 | reinterpret_cast<char *> (dummy + dummy_size - still_to_recv), |
492 | still_to_recv, 0); |
493 | wsa_assert (nbytes != SOCKET_ERROR); |
494 | still_to_recv -= nbytes; |
495 | } |
496 | free (dummy); |
497 | } |
498 | |
499 | // Save errno if error occurred in bind/listen/connect/accept. |
500 | int saved_errno = 0; |
501 | if (*r_ == INVALID_SOCKET) |
502 | saved_errno = WSAGetLastError (); |
503 | |
504 | // We don't need the listening socket anymore. Close it. |
505 | rc = closesocket (listener); |
506 | wsa_assert (rc != SOCKET_ERROR); |
507 | |
508 | if (sync != NULL) { |
509 | // Exit the critical section. |
510 | BOOL brc; |
511 | if (zmq::signaler_port == event_signaler_port) |
512 | brc = SetEvent (sync); |
513 | else |
514 | brc = ReleaseMutex (sync); |
515 | win_assert (brc != 0); |
516 | |
517 | // Release the kernel object |
518 | brc = CloseHandle (sync); |
519 | win_assert (brc != 0); |
520 | } |
521 | |
522 | if (*r_ != INVALID_SOCKET) { |
523 | zmq::make_socket_noninheritable (*r_); |
524 | return 0; |
525 | } |
526 | // Cleanup writer if connection failed |
527 | if (*w_ != INVALID_SOCKET) { |
528 | rc = closesocket (*w_); |
529 | wsa_assert (rc != SOCKET_ERROR); |
530 | *w_ = INVALID_SOCKET; |
531 | } |
532 | // Set errno from saved value |
533 | errno = zmq::wsa_error_to_errno (saved_errno); |
534 | return -1; |
535 | } |
536 | #endif |
537 | |
538 | int zmq::make_fdpair (fd_t *r_, fd_t *w_) |
539 | { |
540 | #if defined ZMQ_HAVE_EVENTFD |
541 | int flags = 0; |
542 | #if defined ZMQ_HAVE_EVENTFD_CLOEXEC |
543 | // Setting this option result in sane behaviour when exec() functions |
544 | // are used. Old sockets are closed and don't block TCP ports, avoid |
545 | // leaks, etc. |
546 | flags |= EFD_CLOEXEC; |
547 | #endif |
548 | fd_t fd = eventfd (0, flags); |
549 | if (fd == -1) { |
550 | errno_assert (errno == ENFILE || errno == EMFILE); |
551 | *w_ = *r_ = -1; |
552 | return -1; |
553 | } |
554 | *w_ = *r_ = fd; |
555 | return 0; |
556 | |
557 | |
558 | #elif defined ZMQ_HAVE_WINDOWS |
559 | #ifdef ZMQ_HAVE_IPC |
560 | ipc_address_t address; |
561 | std::string dirname, filename; |
562 | |
563 | // Create a listening socket. |
564 | SOCKET listener = open_socket (AF_UNIX, SOCK_STREAM, 0); |
565 | if (listener == retired_fd) { |
566 | // This may happen if the library was built on a system supporting AF_UNIX, but the system running doesn't support it. |
567 | goto try_tcpip; |
568 | } |
569 | |
570 | create_ipc_wildcard_address (dirname, filename); |
571 | |
572 | // Initialise the address structure. |
573 | int rc = address.resolve (filename.c_str ()); |
574 | if (rc != 0) { |
575 | goto error_closelistener; |
576 | } |
577 | |
578 | // Bind the socket to the file path. |
579 | rc = bind (listener, const_cast<sockaddr *> (address.addr ()), |
580 | address.addrlen ()); |
581 | if (rc != 0) { |
582 | errno = wsa_error_to_errno (WSAGetLastError ()); |
583 | goto error_closelistener; |
584 | } |
585 | |
586 | // Listen for incoming connections. |
587 | rc = listen (listener, 1); |
588 | if (rc != 0) { |
589 | errno = wsa_error_to_errno (WSAGetLastError ()); |
590 | goto error_closelistener; |
591 | } |
592 | |
593 | sockaddr_un lcladdr; |
594 | socklen_t lcladdr_len = sizeof lcladdr; |
595 | |
596 | rc = getsockname (listener, reinterpret_cast<struct sockaddr *> (&lcladdr), |
597 | &lcladdr_len); |
598 | wsa_assert (rc != -1); |
599 | |
600 | // Create the client socket. |
601 | *w_ = open_socket (AF_UNIX, SOCK_STREAM, 0); |
602 | if (*w_ == -1) { |
603 | errno = wsa_error_to_errno (WSAGetLastError ()); |
604 | goto error_closelistener; |
605 | } |
606 | |
607 | // Connect to the remote peer. |
608 | rc = ::connect (*w_, reinterpret_cast<const struct sockaddr *> (&lcladdr), |
609 | lcladdr_len); |
610 | if (rc == -1) { |
611 | goto error_closeclient; |
612 | } |
613 | |
614 | *r_ = accept (listener, NULL, NULL); |
615 | errno_assert (*r_ != -1); |
616 | |
617 | // Close the listener socket, we don't need it anymore. |
618 | rc = closesocket (listener); |
619 | wsa_assert (rc == 0); |
620 | |
621 | return 0; |
622 | |
623 | error_closeclient: |
624 | int saved_errno = errno; |
625 | rc = closesocket (*w_); |
626 | wsa_assert (rc == 0); |
627 | errno = saved_errno; |
628 | |
629 | error_closelistener: |
630 | saved_errno = errno; |
631 | rc = closesocket (listener); |
632 | wsa_assert (rc == 0); |
633 | errno = saved_errno; |
634 | |
635 | return -1; |
636 | |
637 | try_tcpip: |
638 | // try to fallback to TCP/IP |
639 | // TODO: maybe remember this decision permanently? |
640 | #endif |
641 | |
642 | return make_fdpair_tcpip (r_, w_); |
643 | #elif defined ZMQ_HAVE_OPENVMS |
644 | |
645 | // Whilst OpenVMS supports socketpair - it maps to AF_INET only. Further, |
646 | // it does not set the socket options TCP_NODELAY and TCP_NODELACK which |
647 | // can lead to performance problems. |
648 | // |
649 | // The bug will be fixed in V5.6 ECO4 and beyond. In the meantime, we'll |
650 | // create the socket pair manually. |
651 | struct sockaddr_in lcladdr; |
652 | memset (&lcladdr, 0, sizeof lcladdr); |
653 | lcladdr.sin_family = AF_INET; |
654 | lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
655 | lcladdr.sin_port = 0; |
656 | |
657 | int listener = open_socket (AF_INET, SOCK_STREAM, 0); |
658 | errno_assert (listener != -1); |
659 | |
660 | int on = 1; |
661 | int rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on); |
662 | errno_assert (rc != -1); |
663 | |
664 | rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof on); |
665 | errno_assert (rc != -1); |
666 | |
667 | rc = bind (listener, (struct sockaddr *) &lcladdr, sizeof lcladdr); |
668 | errno_assert (rc != -1); |
669 | |
670 | socklen_t lcladdr_len = sizeof lcladdr; |
671 | |
672 | rc = getsockname (listener, (struct sockaddr *) &lcladdr, &lcladdr_len); |
673 | errno_assert (rc != -1); |
674 | |
675 | rc = listen (listener, 1); |
676 | errno_assert (rc != -1); |
677 | |
678 | *w_ = open_socket (AF_INET, SOCK_STREAM, 0); |
679 | errno_assert (*w_ != -1); |
680 | |
681 | rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on); |
682 | errno_assert (rc != -1); |
683 | |
684 | rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELACK, &on, sizeof on); |
685 | errno_assert (rc != -1); |
686 | |
687 | rc = connect (*w_, (struct sockaddr *) &lcladdr, sizeof lcladdr); |
688 | errno_assert (rc != -1); |
689 | |
690 | *r_ = accept (listener, NULL, NULL); |
691 | errno_assert (*r_ != -1); |
692 | |
693 | close (listener); |
694 | |
695 | return 0; |
696 | #elif defined ZMQ_HAVE_VXWORKS |
697 | struct sockaddr_in lcladdr; |
698 | memset (&lcladdr, 0, sizeof lcladdr); |
699 | lcladdr.sin_family = AF_INET; |
700 | lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
701 | lcladdr.sin_port = 0; |
702 | |
703 | int listener = open_socket (AF_INET, SOCK_STREAM, 0); |
704 | errno_assert (listener != -1); |
705 | |
706 | int on = 1; |
707 | int rc = |
708 | setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof on); |
709 | errno_assert (rc != -1); |
710 | |
711 | rc = bind (listener, (struct sockaddr *) &lcladdr, sizeof lcladdr); |
712 | errno_assert (rc != -1); |
713 | |
714 | socklen_t lcladdr_len = sizeof lcladdr; |
715 | |
716 | rc = getsockname (listener, (struct sockaddr *) &lcladdr, |
717 | (int *) &lcladdr_len); |
718 | errno_assert (rc != -1); |
719 | |
720 | rc = listen (listener, 1); |
721 | errno_assert (rc != -1); |
722 | |
723 | *w_ = open_socket (AF_INET, SOCK_STREAM, 0); |
724 | errno_assert (*w_ != -1); |
725 | |
726 | rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof on); |
727 | errno_assert (rc != -1); |
728 | |
729 | rc = connect (*w_, (struct sockaddr *) &lcladdr, sizeof lcladdr); |
730 | errno_assert (rc != -1); |
731 | |
732 | *r_ = accept (listener, NULL, NULL); |
733 | errno_assert (*r_ != -1); |
734 | |
735 | close (listener); |
736 | |
737 | return 0; |
738 | #else |
739 | // All other implementations support socketpair() |
740 | int sv[2]; |
741 | int type = SOCK_STREAM; |
742 | // Setting this option result in sane behaviour when exec() functions |
743 | // are used. Old sockets are closed and don't block TCP ports, avoid |
744 | // leaks, etc. |
745 | #if defined ZMQ_HAVE_SOCK_CLOEXEC |
746 | type |= SOCK_CLOEXEC; |
747 | #endif |
748 | int rc = socketpair (AF_UNIX, type, 0, sv); |
749 | if (rc == -1) { |
750 | errno_assert (errno == ENFILE || errno == EMFILE); |
751 | *w_ = *r_ = -1; |
752 | return -1; |
753 | } else { |
754 | make_socket_noninheritable (sv[0]); |
755 | make_socket_noninheritable (sv[1]); |
756 | |
757 | *w_ = sv[0]; |
758 | *r_ = sv[1]; |
759 | return 0; |
760 | } |
761 | #endif |
762 | } |
763 | |
764 | void zmq::make_socket_noninheritable (fd_t sock_) |
765 | { |
766 | #if defined ZMQ_HAVE_WINDOWS && !defined _WIN32_WCE \ |
767 | && !defined ZMQ_HAVE_WINDOWS_UWP |
768 | // On Windows, preventing sockets to be inherited by child processes. |
769 | const BOOL brc = SetHandleInformation (reinterpret_cast<HANDLE> (sock_), |
770 | HANDLE_FLAG_INHERIT, 0); |
771 | win_assert (brc); |
772 | #elif (!defined ZMQ_HAVE_SOCK_CLOEXEC || !defined HAVE_ACCEPT4) \ |
773 | && defined FD_CLOEXEC |
774 | // If there 's no SOCK_CLOEXEC, let's try the second best option. |
775 | // Race condition can cause socket not to be closed (if fork happens |
776 | // between accept and this point). |
777 | const int rc = fcntl (sock_, F_SETFD, FD_CLOEXEC); |
778 | errno_assert (rc != -1); |
779 | #else |
780 | LIBZMQ_UNUSED (sock_); |
781 | #endif |
782 | } |
783 | |
784 | void zmq::assert_success_or_recoverable (zmq::fd_t s_, int rc_) |
785 | { |
786 | #ifdef ZMQ_HAVE_WINDOWS |
787 | if (rc_ != SOCKET_ERROR) { |
788 | return; |
789 | } |
790 | #else |
791 | if (rc_ != -1) { |
792 | return; |
793 | } |
794 | #endif |
795 | |
796 | // Check whether an error occurred |
797 | int err = 0; |
798 | #if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_VXWORKS |
799 | int len = sizeof err; |
800 | #else |
801 | socklen_t len = sizeof err; |
802 | #endif |
803 | |
804 | int rc = getsockopt (s_, SOL_SOCKET, SO_ERROR, |
805 | reinterpret_cast<char *> (&err), &len); |
806 | |
807 | // Assert if the error was caused by 0MQ bug. |
808 | // Networking problems are OK. No need to assert. |
809 | #ifdef ZMQ_HAVE_WINDOWS |
810 | zmq_assert (rc == 0); |
811 | if (err != 0) { |
812 | wsa_assert (err == WSAECONNREFUSED || err == WSAECONNRESET |
813 | || err == WSAECONNABORTED || err == WSAEINTR |
814 | || err == WSAETIMEDOUT || err == WSAEHOSTUNREACH |
815 | || err == WSAENETUNREACH || err == WSAENETDOWN |
816 | || err == WSAENETRESET || err == WSAEACCES |
817 | || err == WSAEINVAL || err == WSAEADDRINUSE); |
818 | } |
819 | #else |
820 | // Following code should handle both Berkeley-derived socket |
821 | // implementations and Solaris. |
822 | if (rc == -1) |
823 | err = errno; |
824 | if (err != 0) { |
825 | errno = err; |
826 | errno_assert (errno == ECONNREFUSED || errno == ECONNRESET |
827 | || errno == ECONNABORTED || errno == EINTR |
828 | || errno == ETIMEDOUT || errno == EHOSTUNREACH |
829 | || errno == ENETUNREACH || errno == ENETDOWN |
830 | || errno == ENETRESET || errno == EINVAL); |
831 | } |
832 | #endif |
833 | } |
834 | |
835 | #ifdef ZMQ_HAVE_IPC |
836 | int zmq::create_ipc_wildcard_address (std::string &path_, std::string &file_) |
837 | { |
838 | #if defined ZMQ_HAVE_WINDOWS |
839 | char buffer[MAX_PATH]; |
840 | |
841 | { |
842 | const errno_t rc = tmpnam_s (buffer); |
843 | errno_assert (rc == 0); |
844 | } |
845 | |
846 | // TODO or use CreateDirectoryA and specify permissions? |
847 | const int rc = _mkdir (buffer); |
848 | if (rc != 0) { |
849 | return -1; |
850 | } |
851 | |
852 | path_.assign (buffer); |
853 | file_ = path_ + "/socket" ; |
854 | #else |
855 | std::string tmp_path; |
856 | |
857 | // If TMPDIR, TEMPDIR, or TMP are available and are directories, create |
858 | // the socket directory there. |
859 | const char **tmp_env = tmp_env_vars; |
860 | while (tmp_path.empty () && *tmp_env != 0) { |
861 | char *tmpdir = getenv (*tmp_env); |
862 | struct stat statbuf; |
863 | |
864 | // Confirm it is actually a directory before trying to use |
865 | if (tmpdir != 0 && ::stat (tmpdir, &statbuf) == 0 |
866 | && S_ISDIR (statbuf.st_mode)) { |
867 | tmp_path.assign (tmpdir); |
868 | if (*(tmp_path.rbegin ()) != '/') { |
869 | tmp_path.push_back ('/'); |
870 | } |
871 | } |
872 | |
873 | // Try the next environment variable |
874 | ++tmp_env; |
875 | } |
876 | |
877 | // Append a directory name |
878 | tmp_path.append ("tmpXXXXXX" ); |
879 | |
880 | // We need room for tmp_path + trailing NUL |
881 | std::vector<char> buffer (tmp_path.length () + 1); |
882 | strcpy (&buffer[0], tmp_path.c_str ()); |
883 | |
884 | #if defined HAVE_MKDTEMP |
885 | // Create the directory. POSIX requires that mkdtemp() creates the |
886 | // directory with 0700 permissions, meaning the only possible race |
887 | // with socket creation could be the same user. However, since |
888 | // each socket is created in a directory created by mkdtemp(), and |
889 | // mkdtemp() guarantees a unique directory name, there will be no |
890 | // collision. |
891 | if (mkdtemp (&buffer[0]) == 0) { |
892 | return -1; |
893 | } |
894 | |
895 | path_.assign (&buffer[0]); |
896 | file_ = path_ + "/socket" ; |
897 | #else |
898 | LIBZMQ_UNUSED (path_); |
899 | int fd = mkstemp (&buffer[0]); |
900 | if (fd == -1) |
901 | return -1; |
902 | ::close (fd); |
903 | |
904 | file_.assign (&buffer[0]); |
905 | #endif |
906 | #endif |
907 | |
908 | return 0; |
909 | } |
910 | #endif |
911 | |