46175e9f538e939de73f7aaed5d60d8512b85074
[umurmur.git] / src / server.c
1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
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.
18
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.
30 */
31 #include <stdio.h>
32 #include <sys/time.h>
33 #include <sys/poll.h>
34 #include <netinet/tcp.h>
35 #include <sys/socket.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <limits.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 #include <stdlib.h>
43
44 #include "client.h"
45 #include "conf.h"
46 #include "log.h"
47 #include "timer.h"
48 #include "version.h"
49 #include "util.h"
50
51 /* globals */
52 bool_t shutdown_server;
53 extern char *bindaddr;
54 extern char *bindaddr6;
55 extern int bindport;
56 extern int bindport6;
57 int* udpsocks;
58 bool_t hasv4 = true, hasv6 = true;
59
60 const int on = 1;
61 int nofServerSocks = 4;
62
63 /* Check which IP versions are supported by the system. */
64 void checkIPversions()
65 {
66         int testsocket = -1;
67
68         testsocket = socket(PF_INET, SOCK_STREAM, 0);
69         hasv4 = (errno == EAFNOSUPPORT) ? false : true;
70         if (!(testsocket < 0)) close(testsocket);
71
72         testsocket = socket(PF_INET6, SOCK_STREAM, 0);
73         hasv6 = (errno == EAFNOSUPPORT) ? false : true;
74         if (!(testsocket < 0)) close(testsocket);
75
76         if(!hasv4)
77         {
78                 Log_info("IPv4 is not supported by this system");
79                 nofServerSocks -= 2;
80         }
81
82         if(!hasv6)
83         {
84                 Log_info("IPv6 is not supported by this system");
85                 nofServerSocks -= 2;
86         }
87
88         if(nofServerSocks == 0)
89         {
90                 Log_fatal("Neither IPv4 nor IPv6 are supported by this system");
91         }
92 }
93
94 /* Initialize the address structures for IPv4 and IPv6 */
95 struct sockaddr_storage** Server_setupAddressesAndPorts()
96 {
97         struct sockaddr_storage** addresses = calloc(2, sizeof(void*));
98
99         struct sockaddr_storage* v4address = calloc(1, sizeof(struct sockaddr_storage));
100         v4address->ss_family = AF_INET;
101         struct sockaddr_storage* v6address = calloc(1, sizeof(struct sockaddr_storage));
102         v6address->ss_family = AF_INET6;
103
104 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
105         v4address->ss_len = sizeof(struct sockaddr_storage);
106         v6address->ss_len = sizeof(struct sockaddr_storage);
107 #endif
108
109         int error = 0;
110
111         error = inet_pton(AF_INET, (!bindaddr) ? ((getStrConf(BINDADDR)) ? getStrConf(BINDADDR) : "0.0.0.0")
112                 : bindaddr, &(((struct sockaddr_in*)v4address)->sin_addr));
113         if (error == 0)
114                 Log_fatal("Invalid IPv4 address supplied!");
115         else if (error == -1)
116                 Log_warn("Could not allocate IPv4 address");
117
118         error = inet_pton(AF_INET6, (!bindaddr6) ? ((getStrConf(BINDADDR6)) ? getStrConf(BINDADDR6) : "::")
119                 : bindaddr6, &(((struct sockaddr_in6*)v6address)->sin6_addr));
120         if (error == 0)
121                 Log_fatal("Invalid IPv6 address supplied!");
122         else if (error == -1)
123                 Log_warn("Could not allocate IPv6 address");
124
125         ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
126         ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
127
128         addresses[0] = v4address;
129         addresses[1] = v6address;
130
131         return addresses;
132 }
133
134 void Server_runLoop(struct pollfd* pollfds)
135 {
136         int timeout, rc, clientcount;
137
138         etimer_t janitorTimer;
139         Timer_init(&janitorTimer);
140
141         while (!shutdown_server) {
142                 struct sockaddr_storage remote;
143                 int i;
144
145                 for(i = 0; i < nofServerSocks; i++) {
146                         pollfds[i].revents = 0;
147                 }
148
149                 clientcount = Client_getfds(&pollfds[nofServerSocks]);
150
151                 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
152                 if (timeout <= 0) {
153                         Client_janitor();
154                         Timer_restart(&janitorTimer);
155                         timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
156                 }
157                 rc = poll(pollfds, clientcount + nofServerSocks, timeout);
158                 if (rc == 0) {
159                         /* Poll timed out, do maintenance */
160                         Timer_restart(&janitorTimer);
161                         Client_janitor();
162                         continue;
163                 }
164                 if (rc < 0) {
165                         if (errno == EINTR) /* signal */
166                                 continue;
167                         else
168                                 Log_fatal("poll: error %d (%s)", errno, strerror(errno));
169                 }
170
171                 /* Check for new connection */
172                 for (i = 0; i < nofServerSocks / 2; i++) {
173                         if (pollfds[i].revents) {
174                                 static int tcpfd;
175                                 static uint32_t addrlen = sizeof(struct sockaddr_storage);
176                                 tcpfd = accept(pollfds[i].fd, (struct sockaddr *)&remote, &addrlen);
177                                 fcntl(tcpfd, F_SETFL, O_NONBLOCK);
178                                 setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(int));
179                                 Log_debug("Connection from %s port %d\n", Util_addressToString(&remote), Util_addressToPort(&remote));
180                                 if (Client_add(tcpfd, &remote) < 0)
181                                         close(tcpfd);
182                         }
183                 }
184
185                 for (i = nofServerSocks / 2; i < nofServerSocks; i++) {
186                         if (pollfds[i].revents)
187                                 Client_read_udp(udpsocks[i - nofServerSocks / 2]);
188                 }
189
190                 for (i = 0; i < clientcount; i++) {
191                         if (pollfds[nofServerSocks + i].revents & POLLIN)
192                                 Client_read_fd(pollfds[nofServerSocks + i].fd);
193
194                         if (pollfds[nofServerSocks + i].revents & POLLOUT)
195                                 Client_write_fd(pollfds[nofServerSocks + i].fd);
196                 }
197     Sharedmemory_update();
198         }
199 }
200
201 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
202 {
203         uint8_t yes = 1;
204         int sockets[2];
205
206         if (hasv4) {
207                 /* IPv4 socket setup */
208                 sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
209                 if (sockets[0] < 0)
210                         Log_fatal("socket IPv4");
211                 if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
212                         Log_fatal("setsockopt IPv4: %s", strerror(errno));
213                 if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
214                         Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
215                 if (listen(sockets[0], 3) < 0)
216                         Log_fatal("listen IPv4");
217                 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
218
219                 pollfds[0].fd = sockets[0];
220                 pollfds[0].events = POLLIN;
221         }
222
223         if (hasv6) {
224                 /* IPv6 socket setup */
225                 sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
226                 if (sockets[1] < 0)
227                         Log_fatal("socket IPv6: %s", strerror(errno));
228                 if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
229                         Log_fatal("setsockopt IPv6: %s", strerror(errno));
230                 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
231                         Log_fatal("setsockopt IPv6: %s", strerror(errno));
232                 if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
233                         Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
234                 if (listen(sockets[1], 3) < 0)
235                         Log_fatal("listen IPv6");
236                 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
237
238
239                 /* If  there is an IPv4 address, then IPv6 will use the second socket, otherwise it uses the first */
240                 pollfds[(hasv4) ? 1 : 0].fd = sockets[1];
241                 pollfds[(hasv4) ? 1 : 0].events = POLLIN;
242         }
243 }
244
245 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
246 {
247         int val = 0;
248         int sockets[2] = {-1, -1};
249
250         if((udpsocks = calloc(nofServerSocks / 2, sizeof(int))) == NULL)
251                 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
252
253         if (hasv4) {
254                 sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
255                 if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
256                         Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
257                 val = 0xe0;
258                 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
259                         Log_warn("Server: Failed to set TOS for UDP Socket");
260                 val = 0x80;
261                 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
262                         Log_warn("Server: Failed to set TOS for UDP Socket");
263
264                 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
265                 pollfds[(hasv6) ? 2 : 1].fd = sockets[0];
266                 pollfds[(hasv6) ? 2 : 1].events = POLLIN | POLLHUP | POLLERR;
267                 udpsocks[0] = sockets[0];
268         }
269
270         if (hasv6) {
271                 sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
272                 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)) != 0)
273                         Log_fatal("setsockopt IPv6: %s", strerror(errno));
274                 if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
275                         Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
276                 val = 0xe0;
277                 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
278                         Log_warn("Server: Failed to set TOS for UDP Socket");
279                 val = 0x80;
280                 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
281                         Log_warn("Server: Failed to set TOS for UDP Socket");
282
283                 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
284                 pollfds[(hasv4) ? 3 : 1].fd = sockets[1];
285                 pollfds[(hasv4) ? 3 : 1].events = POLLIN | POLLHUP | POLLERR;
286                 udpsocks[(hasv4) ? 1 : 0] = sockets[1];
287         }
288
289 }
290
291 void Server_run()
292 {
293         struct pollfd *pollfds;
294
295         checkIPversions();
296
297         /* max clients + server sokets + client connecting that will be disconnected */
298         if ((pollfds = calloc((getIntConf(MAX_CLIENTS) + nofServerSocks + 1) , sizeof(struct pollfd))) == NULL)
299                 Log_fatal("out of memory");
300
301         /* Figure out bind address and port */
302         struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
303
304         /* Prepare TCP sockets */
305         Server_setupTCPSockets(addresses, pollfds);
306
307         /* Prepare UDP sockets */
308         Server_setupUDPSockets(addresses, pollfds);
309
310         Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
311                 UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
312         Log_info("Visit http://code.google.com/p/umurmur/");
313
314         /* Main server loop */
315         Server_runLoop(pollfds);
316
317         /* Disconnect clients and cleanup memory */
318         Client_disconnect_all();
319         free(pollfds);
320         free(addresses[0]);
321         free(addresses[1]);
322         free(addresses);
323         free(udpsocks);
324 }
325
326 void Server_shutdown()
327 {
328         shutdown_server = true;
329 }