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 error = inet_pton(AF_INET, (!bindaddr) ? ((getStrConf(BINDADDR)) ? getStrConf(BINDADDR) : "0.0.0.0")
87 : bindaddr, &(((struct sockaddr_in*)v4address)->sin_addr));
88 if (error == 0) Log_fatal("Invalid IPv4 address supplied!");
90 error = inet_pton(AF_INET6, (!bindaddr6) ? ((getStrConf(BINDADDR6)) ? getStrConf(BINDADDR6) : "::")
91 : bindaddr6, &(((struct sockaddr_in6*)v6address)->sin6_addr));
92 if (error == 0) Log_fatal("Invalid IPv6 address supplied!");
94 ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
95 ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
97 addresses[0] = v4address;
98 addresses[1] = v6address;
103 void Server_runLoop(struct pollfd* pollfds)
105 int timeout, rc, clientcount;
107 etimer_t janitorTimer;
108 Timer_init(&janitorTimer);
110 while (!shutdown_server) {
111 struct sockaddr_storage remote;
114 pollfds[UDP_SOCK].revents = 0;
115 pollfds[UDP_SOCK6].revents = 0;
116 pollfds[TCP_SOCK].revents = 0;
117 pollfds[TCP_SOCK6].revents = 0;
118 clientcount = Client_getfds(&pollfds[SERVER_SOCKS]);
120 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
123 Timer_restart(&janitorTimer);
124 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
126 rc = poll(pollfds, clientcount + SERVER_SOCKS, timeout);
128 /* Poll timed out, do maintenance */
129 Timer_restart(&janitorTimer);
134 if (errno == EINTR) /* signal */
137 Log_fatal("poll: error %d (%s)", errno, strerror(errno));
140 /* Check for new connection */
141 for (i = 0; i < TCP_SOCKS; i++) {
142 if (pollfds[i].revents) {
144 static uint32_t addrlen = sizeof(struct sockaddr_storage);
145 tcpfd = accept(pollfds[i].fd, (struct sockaddr *)&remote, &addrlen);
146 fcntl(tcpfd, F_SETFL, O_NONBLOCK);
147 setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(int));
148 Log_debug("Connection from %s port %d\n", Util_addressToString(&remote), Util_addressToPort(&remote));
149 if (Client_add(tcpfd, &remote) < 0)
154 for (i = 2; i < SERVER_SOCKS; i++) {
155 if (pollfds[i].revents) {
156 Client_read_udp(udpsocks[i - UDP_SOCKS]);
160 for (i = 0; i < clientcount; i++) {
161 if (pollfds[i + 4].revents & POLLIN) {
162 Client_read_fd(pollfds[i + 4].fd);
164 if (pollfds[i + 4].revents & POLLOUT) {
165 Client_write_fd(pollfds[i + 4].fd);
171 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
176 /* IPv4 socket setup */
177 sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
179 Log_fatal("socket IPv4");
180 if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
181 Log_fatal("setsockopt IPv4: %s", strerror(errno));
182 if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
183 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
184 if (listen(sockets[0], 3) < 0)
185 Log_fatal("listen IPv4");
186 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
188 pollfds[TCP_SOCK].fd = sockets[0];
189 pollfds[TCP_SOCK].events = POLLIN;
191 /* IPv6 socket setup */
192 sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
194 Log_fatal("socket IPv6");
195 if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
196 Log_fatal("setsockopt IPv6: %s", strerror(errno));
197 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
198 Log_fatal("setsockopt IPv6: %s", strerror(errno));
199 if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
200 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
201 if (listen(sockets[1], 3) < 0)
202 Log_fatal("listen IPv6");
203 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
205 pollfds[TCP_SOCK6].fd = sockets[1];
206 pollfds[TCP_SOCK6].events = POLLIN;
209 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
214 if((udpsocks = malloc(2 * sizeof(int))) == NULL)
215 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
217 sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
218 if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
219 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
221 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
222 Log_warn("Server: Failed to set TOS for UDP Socket");
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 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
228 pollfds[UDP_SOCK].fd = sockets[0];
229 pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
231 sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
232 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)) != 0)
233 Log_fatal("setsockopt IPv6: %s", strerror(errno));
234 if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
235 Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
237 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
238 Log_warn("Server: Failed to set TOS for UDP Socket");
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 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
244 pollfds[UDP_SOCK6].fd = sockets[1];
245 pollfds[UDP_SOCK6].events = POLLIN | POLLHUP | POLLERR;
246 udpsocks[UDP_SOCK - UDP_SOCKS] = sockets[0];
247 udpsocks[UDP_SOCK6 - UDP_SOCKS] = sockets[1];
252 struct pollfd *pollfds;
254 /* max clients + listen sock + udp sock + client connecting that will be disconnected */
255 if ((pollfds = calloc((getIntConf(MAX_CLIENTS) + 5) , sizeof(struct pollfd))) == NULL)
256 Log_fatal("out of memory");
258 /* Figure out bind address and port */
259 struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
261 /* Prepare TCP sockets */
262 Server_setupTCPSockets(addresses, pollfds);
264 /* Prepare UDP sockets */
265 Server_setupUDPSockets(addresses, pollfds);
267 Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
268 UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
269 Log_info("Visit http://code.google.com/p/umurmur/");
271 /* Main server loop */
272 Server_runLoop(pollfds);
274 /* Disconnect clients and cleanup memory */
275 Client_disconnect_all();
283 void Server_shutdown()
285 shutdown_server = true;