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 #define SERVER_SOCKS UDP_SOCKS + TCP_SOCKS
60 bool_t shutdown_server;
61 extern char *bindaddr;
62 extern char *bindaddr6;
69 /* Initialize the address structures for IPv4 and IPv6 */
70 struct sockaddr_storage** Server_setupAddressesAndPorts()
72 struct sockaddr_storage** addresses = malloc(2 * sizeof(void*));
74 struct sockaddr_storage* v4address = calloc(1, sizeof(struct sockaddr_storage));
75 v4address->ss_family = AF_INET;
76 struct sockaddr_storage* v6address = calloc(1, sizeof(struct sockaddr_storage));
77 v6address->ss_family = AF_INET6;
79 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
80 v4address->ss_len = sizeof(struct sockaddr_storage);
81 v6address->ss_len = sizeof(struct sockaddr_storage);
86 const char* confadd = getStrConf(BINDADDR);
87 error = inet_pton(AF_INET, (!bindaddr) ? ((getStrConf(BINDADDR)) ? getStrConf(BINDADDR) : "0.0.0.0")
88 : bindaddr, &(((struct sockaddr_in*)v4address)->sin_addr));
89 if (error == 0) Log_fatal("Invalid IPv4 address supplied!");
91 error = inet_pton(AF_INET6, (!bindaddr6) ? ((getStrConf(BINDADDR6)) ? getStrConf(BINDADDR6) : "::")
92 : bindaddr6, &(((struct sockaddr_in6*)v6address)->sin6_addr));
93 if (error == 0) Log_fatal("Invalid IPv6 address supplied!");
95 ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
96 ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
98 addresses[0] = v4address;
99 addresses[1] = v6address;
104 void Server_runLoop(struct pollfd* pollfds)
106 int timeout, rc, clientcount;
108 etimer_t janitorTimer;
109 Timer_init(&janitorTimer);
111 while (!shutdown_server) {
112 struct sockaddr_storage remote;
115 pollfds[UDP_SOCK].revents = 0;
116 pollfds[UDP_SOCK6].revents = 0;
117 pollfds[TCP_SOCK].revents = 0;
118 pollfds[TCP_SOCK6].revents = 0;
119 clientcount = Client_getfds(&pollfds[SERVER_SOCKS]);
121 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
124 Timer_restart(&janitorTimer);
125 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
127 rc = poll(pollfds, clientcount + SERVER_SOCKS, timeout);
129 /* Poll timed out, do maintenance */
130 Timer_restart(&janitorTimer);
135 if (errno == EINTR) /* signal */
138 Log_fatal("poll: error %d (%s)", errno, strerror(errno));
141 /* Check for new connection */
142 for (i = 0; i < TCP_SOCKS; i++) {
143 if (pollfds[i].revents) {
145 static uint32_t addrlen = sizeof(struct sockaddr_storage);
146 tcpfd = accept(pollfds[i].fd, (struct sockaddr *)&remote, &addrlen);
147 fcntl(tcpfd, F_SETFL, O_NONBLOCK);
148 setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(int));
149 Log_debug("Connection from %s port %d\n", Util_addressToString(&remote), Util_addressToPort(&remote));
150 if (Client_add(tcpfd, &remote) < 0)
155 for (i = 2; i < SERVER_SOCKS; i++) {
156 if (pollfds[i].revents) {
157 Client_read_udp(udpsocks[i - UDP_SOCKS]);
161 for (i = 0; i < clientcount; i++) {
162 if (pollfds[i + 4].revents & POLLIN) {
163 Client_read_fd(pollfds[i + 4].fd);
165 if (pollfds[i + 4].revents & POLLOUT) {
166 Client_write_fd(pollfds[i + 4].fd);
172 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
178 /* IPv4 socket setup */
179 sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
181 Log_fatal("socket IPv4");
182 if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
183 Log_fatal("setsockopt IPv4: %s", strerror(errno));
184 if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
185 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
186 if (listen(sockets[0], 3) < 0)
187 Log_fatal("listen IPv4");
188 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
190 pollfds[TCP_SOCK].fd = sockets[0];
191 pollfds[TCP_SOCK].events = POLLIN;
193 /* IPv6 socket setup */
194 sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
196 Log_fatal("socket IPv6");
197 if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
198 Log_fatal("setsockopt IPv6: %s", strerror(errno));
199 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
200 Log_fatal("setsockopt IPv6: %s", strerror(errno));
201 if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
202 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
203 if (listen(sockets[1], 3) < 0)
204 Log_fatal("listen IPv6");
205 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
207 pollfds[TCP_SOCK6].fd = sockets[1];
208 pollfds[TCP_SOCK6].events = POLLIN;
211 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
217 if((udpsocks = malloc(2 * sizeof(int))) == NULL)
218 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
220 sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
221 if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
222 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
224 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
225 Log_warn("Server: Failed to set TOS for UDP Socket");
227 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
228 Log_warn("Server: Failed to set TOS for UDP Socket");
230 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
231 pollfds[UDP_SOCK].fd = sockets[0];
232 pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
234 sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
235 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)) != 0)
236 Log_fatal("setsockopt IPv6: %s", strerror(errno));
237 if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
238 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
240 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
241 Log_warn("Server: Failed to set TOS for UDP Socket");
243 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
244 Log_warn("Server: Failed to set TOS for UDP Socket");
246 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
247 pollfds[UDP_SOCK6].fd = sockets[1];
248 pollfds[UDP_SOCK6].events = POLLIN | POLLHUP | POLLERR;
249 udpsocks[UDP_SOCK - UDP_SOCKS] = sockets[0];
250 udpsocks[UDP_SOCK6 - UDP_SOCKS] = sockets[1];
255 struct pollfd *pollfds;
257 /* max clients + listen sock + udp sock + client connecting that will be disconnected */
258 if ((pollfds = calloc((getIntConf(MAX_CLIENTS) + 5) , sizeof(struct pollfd))) == NULL)
259 Log_fatal("out of memory");
261 /* Figure out bind address and port */
262 struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
264 /* Prepare TCP sockets */
265 Server_setupTCPSockets(addresses, pollfds);
267 /* Prepare UDP sockets */
268 Server_setupUDPSockets(addresses, pollfds);
270 Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
271 UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
272 Log_info("Visit http://code.google.com/p/umurmur/");
274 /* Main server loop */
275 Server_runLoop(pollfds);
277 /* Disconnect clients and cleanup memory */
278 Client_disconnect_all();
286 void Server_shutdown()
288 shutdown_server = true;