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 <new>
32
33#include <string>
34#include <stdio.h>
35
36#include "tcp_listener.hpp"
37#include "io_thread.hpp"
38#include "config.hpp"
39#include "err.hpp"
40#include "ip.hpp"
41#include "tcp.hpp"
42#include "socket_base.hpp"
43#include "address.hpp"
44
45#ifndef ZMQ_HAVE_WINDOWS
46#include <unistd.h>
47#include <sys/socket.h>
48#include <arpa/inet.h>
49#include <netinet/tcp.h>
50#include <netinet/in.h>
51#include <netdb.h>
52#include <fcntl.h>
53#ifdef ZMQ_HAVE_VXWORKS
54#include <sockLib.h>
55#endif
56#endif
57
58#ifdef ZMQ_HAVE_OPENVMS
59#include <ioctl.h>
60#endif
61
62zmq::tcp_listener_t::tcp_listener_t (io_thread_t *io_thread_,
63 socket_base_t *socket_,
64 const options_t &options_) :
65 stream_listener_base_t (io_thread_, socket_, options_)
66{
67}
68
69void zmq::tcp_listener_t::in_event ()
70{
71 fd_t fd = accept ();
72
73 // If connection was reset by the peer in the meantime, just ignore it.
74 // TODO: Handle specific errors like ENFILE/EMFILE etc.
75 if (fd == retired_fd) {
76 _socket->event_accept_failed (
77 make_unconnected_bind_endpoint_pair (_endpoint), zmq_errno ());
78 return;
79 }
80
81 int rc = tune_tcp_socket (fd);
82 rc = rc
83 | tune_tcp_keepalives (
84 fd, options.tcp_keepalive, options.tcp_keepalive_cnt,
85 options.tcp_keepalive_idle, options.tcp_keepalive_intvl);
86 rc = rc | tune_tcp_maxrt (fd, options.tcp_maxrt);
87 if (rc != 0) {
88 _socket->event_accept_failed (
89 make_unconnected_bind_endpoint_pair (_endpoint), zmq_errno ());
90 return;
91 }
92
93 // Create the engine object for this connection.
94 create_engine (fd);
95}
96
97std::string
98zmq::tcp_listener_t::get_socket_name (zmq::fd_t fd_,
99 socket_end_t socket_end_) const
100{
101 return zmq::get_socket_name<tcp_address_t> (fd_, socket_end_);
102}
103
104int zmq::tcp_listener_t::create_socket (const char *addr_)
105{
106 _s = tcp_open_socket (addr_, options, true, true, &_address);
107 if (_s == retired_fd) {
108 return -1;
109 }
110
111 // TODO why is this only done for the listener?
112 make_socket_noninheritable (_s);
113
114 // Allow reusing of the address.
115 int flag = 1;
116 int rc;
117#ifdef ZMQ_HAVE_WINDOWS
118 // TODO this was changed for Windows from SO_REUSEADDRE to
119 // SE_EXCLUSIVEADDRUSE by 0ab65324195ad70205514d465b03d851a6de051c,
120 // so the comment above is no longer correct; also, now the settings are
121 // different between listener and connecter with a src address.
122 // is this intentional?
123 rc = setsockopt (_s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
124 reinterpret_cast<const char *> (&flag), sizeof (int));
125 wsa_assert (rc != SOCKET_ERROR);
126#elif defined ZMQ_HAVE_VXWORKS
127 rc =
128 setsockopt (_s, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof (int));
129 errno_assert (rc == 0);
130#else
131 rc = setsockopt (_s, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int));
132 errno_assert (rc == 0);
133#endif
134
135 // Bind the socket to the network interface and port.
136#if defined ZMQ_HAVE_VXWORKS
137 rc = bind (_s, (sockaddr *) _address.addr (), _address.addrlen ());
138#else
139 rc = bind (_s, _address.addr (), _address.addrlen ());
140#endif
141#ifdef ZMQ_HAVE_WINDOWS
142 if (rc == SOCKET_ERROR) {
143 errno = wsa_error_to_errno (WSAGetLastError ());
144 goto error;
145 }
146#else
147 if (rc != 0)
148 goto error;
149#endif
150
151 // Listen for incoming connections.
152 rc = listen (_s, options.backlog);
153#ifdef ZMQ_HAVE_WINDOWS
154 if (rc == SOCKET_ERROR) {
155 errno = wsa_error_to_errno (WSAGetLastError ());
156 goto error;
157 }
158#else
159 if (rc != 0)
160 goto error;
161#endif
162
163 return 0;
164
165error:
166 int err = errno;
167 close ();
168 errno = err;
169 return -1;
170}
171
172int zmq::tcp_listener_t::set_local_address (const char *addr_)
173{
174 if (options.use_fd != -1) {
175 // in this case, the addr_ passed is not used and ignored, since the
176 // socket was already created by the application
177 _s = options.use_fd;
178 } else {
179 if (create_socket (addr_) == -1)
180 return -1;
181 }
182
183 _endpoint = get_socket_name (_s, socket_end_local);
184
185 _socket->event_listening (make_unconnected_bind_endpoint_pair (_endpoint),
186 _s);
187 return 0;
188}
189
190zmq::fd_t zmq::tcp_listener_t::accept ()
191{
192 // The situation where connection cannot be accepted due to insufficient
193 // resources is considered valid and treated by ignoring the connection.
194 // Accept one connection and deal with different failure modes.
195 zmq_assert (_s != retired_fd);
196
197 struct sockaddr_storage ss;
198 memset (&ss, 0, sizeof (ss));
199#if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_VXWORKS
200 int ss_len = sizeof (ss);
201#else
202 socklen_t ss_len = sizeof (ss);
203#endif
204#if defined ZMQ_HAVE_SOCK_CLOEXEC && defined HAVE_ACCEPT4
205 fd_t sock = ::accept4 (_s, reinterpret_cast<struct sockaddr *> (&ss),
206 &ss_len, SOCK_CLOEXEC);
207#else
208 fd_t sock =
209 ::accept (_s, reinterpret_cast<struct sockaddr *> (&ss), &ss_len);
210#endif
211
212 if (sock == retired_fd) {
213#if defined ZMQ_HAVE_WINDOWS
214 const int last_error = WSAGetLastError ();
215 wsa_assert (last_error == WSAEWOULDBLOCK || last_error == WSAECONNRESET
216 || last_error == WSAEMFILE || last_error == WSAENOBUFS);
217#elif defined ZMQ_HAVE_ANDROID
218 errno_assert (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR
219 || errno == ECONNABORTED || errno == EPROTO
220 || errno == ENOBUFS || errno == ENOMEM || errno == EMFILE
221 || errno == ENFILE || errno == EINVAL);
222#else
223 errno_assert (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR
224 || errno == ECONNABORTED || errno == EPROTO
225 || errno == ENOBUFS || errno == ENOMEM || errno == EMFILE
226 || errno == ENFILE);
227#endif
228 return retired_fd;
229 }
230
231 make_socket_noninheritable (sock);
232
233 if (!options.tcp_accept_filters.empty ()) {
234 bool matched = false;
235 for (options_t::tcp_accept_filters_t::size_type i = 0;
236 i != options.tcp_accept_filters.size (); ++i) {
237 if (options.tcp_accept_filters[i].match_address (
238 reinterpret_cast<struct sockaddr *> (&ss), ss_len)) {
239 matched = true;
240 break;
241 }
242 }
243 if (!matched) {
244#ifdef ZMQ_HAVE_WINDOWS
245 int rc = closesocket (sock);
246 wsa_assert (rc != SOCKET_ERROR);
247#else
248 int rc = ::close (sock);
249 errno_assert (rc == 0);
250#endif
251 return retired_fd;
252 }
253 }
254
255 if (zmq::set_nosigpipe (sock)) {
256#ifdef ZMQ_HAVE_WINDOWS
257 int rc = closesocket (sock);
258 wsa_assert (rc != SOCKET_ERROR);
259#else
260 int rc = ::close (sock);
261 errno_assert (rc == 0);
262#endif
263 return retired_fd;
264 }
265
266 // Set the IP Type-Of-Service priority for this client socket
267 if (options.tos != 0)
268 set_ip_type_of_service (sock, options.tos);
269
270 return sock;
271}
272