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>
52 bool_t shutdown_server;
53 extern char *bindaddr;
54 extern char *bindaddr6;
58 bool_t hasv4 = true, hasv6 = true;
61 int nofServerSocks = 4;
63 /* Initialize the address structures for IPv4 and IPv6 */
64 struct sockaddr_storage** Server_setupAddressesAndPorts()
66 struct sockaddr_storage** addresses = calloc(2, sizeof(void*));
68 struct sockaddr_storage* v4address = calloc(1, sizeof(struct sockaddr_storage));
69 v4address->ss_family = AF_INET;
70 struct sockaddr_storage* v6address = calloc(1, sizeof(struct sockaddr_storage));
71 v6address->ss_family = AF_INET6;
73 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
74 v4address->ss_len = sizeof(struct sockaddr_storage);
75 v6address->ss_len = sizeof(struct sockaddr_storage);
80 error = inet_pton(AF_INET, (!bindaddr) ? ((getStrConf(BINDADDR)) ? getStrConf(BINDADDR) : "0.0.0.0")
81 : bindaddr, &(((struct sockaddr_in*)v4address)->sin_addr));
83 Log_fatal("Invalid IPv4 address supplied!");
84 else if (error == -1) {
85 Log_warn("Could not allocate IPv4 address");
90 error = inet_pton(AF_INET6, (!bindaddr6) ? ((getStrConf(BINDADDR6)) ? getStrConf(BINDADDR6) : "::")
91 : bindaddr6, &(((struct sockaddr_in6*)v6address)->sin6_addr));
93 Log_fatal("Invalid IPv6 address supplied!");
94 else if (error == -1) {
95 Log_warn("Could not allocate IPv6 address");
100 if (!hasv4 && !hasv6)
101 Log_fatal("Could not allocate IPv4 nor IPv6 address!");
103 ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
104 ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
106 addresses[0] = v4address;
107 addresses[1] = v6address;
112 void Server_runLoop(struct pollfd* pollfds)
114 int timeout, rc, clientcount;
116 etimer_t janitorTimer;
117 Timer_init(&janitorTimer);
119 while (!shutdown_server) {
120 struct sockaddr_storage remote;
123 if (nofServerSocks == 4) {
124 pollfds[0].revents = 0;
125 pollfds[1].revents = 0;
126 pollfds[2].revents = 0;
127 pollfds[3].revents = 0;
129 pollfds[0].revents = 0;
130 pollfds[1].revents = 0;
133 clientcount = Client_getfds(&pollfds[nofServerSocks]);
135 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
138 Timer_restart(&janitorTimer);
139 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
141 rc = poll(pollfds, clientcount + nofServerSocks, timeout);
143 /* Poll timed out, do maintenance */
144 Timer_restart(&janitorTimer);
149 if (errno == EINTR) /* signal */
152 Log_fatal("poll: error %d (%s)", errno, strerror(errno));
155 /* Check for new connection */
156 for (i = 0; i < nofServerSocks / 2; i++) {
157 if (pollfds[i].revents) {
159 static uint32_t addrlen = sizeof(struct sockaddr_storage);
160 tcpfd = accept(pollfds[i].fd, (struct sockaddr *)&remote, &addrlen);
161 fcntl(tcpfd, F_SETFL, O_NONBLOCK);
162 setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(int));
163 Log_debug("Connection from %s port %d\n", Util_addressToString(&remote), Util_addressToPort(&remote));
164 if (Client_add(tcpfd, &remote) < 0)
169 for (i = nofServerSocks / 2; i < nofServerSocks; i++) {
170 if (pollfds[i].revents)
171 Client_read_udp(udpsocks[i - nofServerSocks / 2]);
174 for (i = 0; i < clientcount; i++) {
175 if (pollfds[nofServerSocks + i].revents & POLLIN)
176 Client_read_fd(pollfds[nofServerSocks + i].fd);
178 if (pollfds[nofServerSocks + i].revents & POLLOUT)
179 Client_write_fd(pollfds[nofServerSocks + i].fd);
184 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
190 /* IPv4 socket setup */
191 sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
193 Log_fatal("socket IPv4");
194 if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
195 Log_fatal("setsockopt IPv4: %s", strerror(errno));
196 if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
197 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
198 if (listen(sockets[0], 3) < 0)
199 Log_fatal("listen IPv4");
200 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
202 pollfds[0].fd = sockets[0];
203 pollfds[0].events = POLLIN;
207 /* IPv6 socket setup */
208 sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
210 Log_fatal("socket IPv6");
211 if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
212 Log_fatal("setsockopt IPv6: %s", strerror(errno));
213 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
214 Log_fatal("setsockopt IPv6: %s", strerror(errno));
215 if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
216 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
217 if (listen(sockets[1], 3) < 0)
218 Log_fatal("listen IPv6");
219 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
222 /* If there is an IPv4 address, then IPv6 will use the second socket, otherwise it uses the first */
223 pollfds[(hasv4) ? 1 : 0].fd = sockets[1];
224 pollfds[(hasv4) ? 1 : 0].events = POLLIN;
228 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
231 int sockets[2] = {-1, -1};
233 if((udpsocks = calloc(nofServerSocks / 2, sizeof(int))) == NULL)
234 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
237 sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
238 if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
239 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
241 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
242 Log_warn("Server: Failed to set TOS for UDP Socket");
244 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
245 Log_warn("Server: Failed to set TOS for UDP Socket");
247 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
248 pollfds[(hasv6) ? 2 : 1].fd = sockets[0];
249 pollfds[(hasv6) ? 2 : 1].events = POLLIN | POLLHUP | POLLERR;
250 udpsocks[0] = sockets[0];
254 sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
255 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)) != 0)
256 Log_fatal("setsockopt IPv6: %s", strerror(errno));
257 if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
258 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
260 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
261 Log_warn("Server: Failed to set TOS for UDP Socket");
263 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
264 Log_warn("Server: Failed to set TOS for UDP Socket");
266 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
267 pollfds[(hasv4) ? 3 : 1].fd = sockets[1];
268 pollfds[(hasv4) ? 3 : 1].events = POLLIN | POLLHUP | POLLERR;
269 udpsocks[(hasv4) ? 1 : 0] = sockets[1];
276 struct pollfd *pollfds;
278 /* max clients + listen sock + udp sock + client connecting that will be disconnected */
279 if ((pollfds = calloc((getIntConf(MAX_CLIENTS) + 5) , sizeof(struct pollfd))) == NULL)
280 Log_fatal("out of memory");
282 /* Figure out bind address and port */
283 struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
285 /* Prepare TCP sockets */
286 Server_setupTCPSockets(addresses, pollfds);
288 /* Prepare UDP sockets */
289 Server_setupUDPSockets(addresses, pollfds);
291 Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
292 UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
293 Log_info("Visit http://code.google.com/p/umurmur/");
295 /* Main server loop */
296 Server_runLoop(pollfds);
298 /* Disconnect clients and cleanup memory */
299 Client_disconnect_all();
307 void Server_shutdown()
309 shutdown_server = true;