1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2 Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 - Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 - Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15 - Neither the name of the Developers nor the names of its contributors may
16 be used to endorse or promote products derived from this software without
17 specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <netinet/tcp.h>
35 #include <sys/socket.h>
57 bool_t shutdown_server;
58 extern char *bindaddr;
59 extern char *bindaddr6;
65 /* Initialize the address structures for IPv4 and IPv6 */
66 struct sockaddr_storage** Server_setupAddressesAndPorts()
68 struct sockaddr_storage** addresses = malloc(2 * sizeof(void*));
70 struct sockaddr_storage* v4address = calloc(1, sizeof(struct sockaddr_storage));
71 v4address->ss_family = AF_INET;
72 struct sockaddr_storage* v6address = calloc(1, sizeof(struct sockaddr_storage));
73 v6address->ss_family = AF_INET6;
75 #if defined(NETBSD) || defined(FREEBSD) || defined(OPENBSD) || defined(__APPLE__)
76 v4address->ss_len = sizeof(struct sockaddr_storage);
77 v6address->ss_len = sizeof(struct sockaddr_storage);
82 const char* confadd = getStrConf(BINDADDR);
83 error = inet_pton(AF_INET, (!bindaddr) ? ((getStrConf(BINDADDR)) ? getStrConf(BINDADDR) : "0.0.0.0")
84 : bindaddr, &(((struct sockaddr_in*)v4address)->sin_addr));
85 if (error == 0) Log_fatal("Invalid IPv4 address supplied!");
87 error = inet_pton(AF_INET6, (!bindaddr6) ? ((getStrConf(BINDADDR6)) ? getStrConf(BINDADDR6) : "::")
88 : bindaddr6, &(((struct sockaddr_in6*)v6address)->sin6_addr));
89 if (error == 0) Log_fatal("Invalid IPv6 address supplied!");
91 ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
92 ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
94 addresses[0] = v4address;
95 addresses[1] = v6address;
100 void Server_runLoop(struct pollfd* pollfds)
102 int timeout = 1000, rc, clientcount;
104 etimer_t janitorTimer;
105 Timer_init(&janitorTimer);
107 while (!shutdown_server) {
108 struct sockaddr_storage remote;
111 pollfds[UDP_SOCK].revents = 0;
112 pollfds[UDP_SOCK6].revents = 0;
113 pollfds[TCP_SOCK].revents = 0;
114 pollfds[TCP_SOCK6].revents = 0;
115 clientcount = Client_getfds(&pollfds[4]);
117 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
120 Timer_restart(&janitorTimer);
121 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
123 rc = poll(pollfds, clientcount + 4, timeout);
124 if (rc == 0) { /* Timeout */
126 Timer_restart(&janitorTimer);
131 if (errno == EINTR) /* signal */
134 Log_fatal("poll: error %d", errno);
136 if (pollfds[TCP_SOCK].revents) { /* New tcp connection */
139 addrlen = sizeof(struct sockaddr_in);
140 tcpfd = accept(pollfds[TCP_SOCK].fd, (struct sockaddr*)&remote, &addrlen);
141 fcntl(tcpfd, F_SETFL, O_NONBLOCK);
142 setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
143 Log_debug("Connection from %s port %d\n", inet_ntoa(((struct sockaddr_in*)&remote)->sin_addr),
144 ntohs(((struct sockaddr_in*)&remote)->sin_port));
145 if (Client_add(tcpfd, &remote) < 0)
149 if (pollfds[TCP_SOCK6].revents) { /* New tcp connection */
152 addrlen = sizeof(struct sockaddr_in6);
153 tcpfd = accept(pollfds[TCP_SOCK6].fd, (struct sockaddr*)&remote, &addrlen);
154 fcntl(tcpfd, F_SETFL, O_NONBLOCK);
155 setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
156 if (Client_add(tcpfd, &remote) < 0)
160 if (pollfds[UDP_SOCK].revents) {
161 Client_read_udp(udpsocks[0]);
163 if (pollfds[UDP_SOCK6].revents) {
164 Client_read_udp(udpsocks[1]);
166 for (i = 0; i < clientcount; i++) {
167 if (pollfds[i + 4].revents & POLLIN) {
168 Client_read_fd(pollfds[i + 4].fd);
170 if (pollfds[i + 4].revents & POLLOUT) {
171 Client_write_fd(pollfds[i + 4].fd);
177 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
183 /* IPv4 socket setup */
184 sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
186 Log_fatal("socket IPv4");
187 if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
188 Log_fatal("setsockopt IPv4: %s", strerror(errno));
189 if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
190 Log_fatal("bind IPv4: %s", strerror(errno));
191 if (listen(sockets[0], 3) < 0)
192 Log_fatal("listen IPv4");
193 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
195 pollfds[TCP_SOCK].fd = sockets[0];
196 pollfds[TCP_SOCK].events = POLLIN;
198 /* IPv6 socket setup */
199 sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
201 Log_fatal("socket IPv6");
202 if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
203 Log_fatal("setsockopt IPv6: %s", strerror(errno));
204 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
205 Log_fatal("setsockopt IPv6: %s", strerror(errno));
206 if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
207 Log_fatal("bind IPv6: %s", strerror(errno));
208 if (listen(sockets[1], 3) < 0)
209 Log_fatal("listen IPv6");
210 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
212 pollfds[TCP_SOCK6].fd = sockets[1];
213 pollfds[TCP_SOCK6].events = POLLIN;
216 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
222 char ipv6Representation[INET6_ADDRSTRLEN];
224 if((udpsocks = malloc(2 * sizeof(int))) == NULL)
225 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
227 inet_ntop(AF_INET6, &((struct sockaddr_in6*)addresses[1])->sin6_addr, ipv6Representation, sizeof(INET6_ADDRSTRLEN));
229 sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
230 if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
231 Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[0])->sin_port,
232 inet_ntoa(((struct sockaddr_in*)addresses[0])->sin_addr), strerror(errno));
234 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
235 Log_warn("Server: Failed to set TOS for UDP Socket");
237 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
238 Log_warn("Server: Failed to set TOS for UDP Socket");
240 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
241 pollfds[UDP_SOCK].fd = sockets[0];
242 pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
244 sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
245 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
246 Log_fatal("setsockopt IPv6: %s", strerror(errno));
247 if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
248 Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[1])->sin_port, ipv6Representation, strerror(errno));
250 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
251 Log_warn("Server: Failed to set TOS for UDP Socket");
253 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
254 Log_warn("Server: Failed to set TOS for UDP Socket");
256 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
257 pollfds[UDP_SOCK6].fd = sockets[1];
258 pollfds[UDP_SOCK6].events = POLLIN | POLLHUP | POLLERR;
259 udpsocks[0] = sockets[0];
260 udpsocks[1] = sockets[1];
265 struct pollfd *pollfds;
267 /* max clients + listen sock + udp sock + client connecting that will be disconnected */
268 if ((pollfds = calloc((getIntConf(MAX_CLIENTS) + 5) , sizeof(struct pollfd))) == NULL)
269 Log_fatal("out of memory");
271 /* Figure out bind address and port */
272 struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
274 /* Prepare TCP sockets */
275 Server_setupTCPSockets(addresses, pollfds);
277 /* Prepare UDP sockets */
278 Server_setupUDPSockets(addresses, pollfds);
280 Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
281 UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
282 Log_info("Visit http://code.google.com/p/umurmur/");
284 /* Main server loop */
285 Server_runLoop(pollfds);
287 /* Disconnect clients and cleanup memory */
288 Client_disconnect_all();
296 void Server_shutdown()
298 shutdown_server = true;