c58264331d488cd2e42bf561a7c406cfb4dfc80c
[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
50 #define TCP_SOCK  0
51 #define TCP_SOCK6 1
52
53 #define UDP_SOCK  2
54 #define UDP_SOCK6 3
55
56 /* globals */
57 bool_t shutdown_server;
58 extern char *bindaddr;
59 extern char *bindaddr6;
60 extern int bindport;
61 extern int bindport6;
62
63 int* udpsocks;
64
65 /* Initialize the address structures for IPv4 and IPv6 */
66 struct sockaddr_storage** Server_setupAddressesAndPorts()
67 {
68         struct sockaddr_storage** addresses = malloc(2 * sizeof(void*));
69
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;
74
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);
78 #endif
79
80         int error = 0;
81
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!");
86
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!");
90
91         ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
92         ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
93
94         addresses[0] = v4address;
95         addresses[1] = v6address;
96
97         return addresses;
98 }
99
100 void Server_runLoop(struct pollfd* pollfds)
101 {
102         int timeout = 1000, rc, clientcount;
103
104         etimer_t janitorTimer;
105         Timer_init(&janitorTimer);
106
107         while (!shutdown_server) {
108                 struct sockaddr_storage remote;
109                 int i;
110
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]);
116
117                 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
118                 if (timeout <= 0) {
119                         Client_janitor();
120                         Timer_restart(&janitorTimer);
121                         timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
122                 }
123                 rc = poll(pollfds, clientcount + 4, timeout);
124                 if (rc == 0) { /* Timeout */
125                         /* Do maintenance */
126                         Timer_restart(&janitorTimer);
127                         Client_janitor();
128                         continue;
129                 }
130                 if (rc < 0) {
131                         if (errno == EINTR) /* signal */
132                                 continue;
133                         else
134                                 Log_fatal("poll: error %d", errno);
135                 }
136                 if (pollfds[TCP_SOCK].revents) { /* New tcp connection */
137                         int tcpfd, flag = 1;
138                         uint32_t addrlen;
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)
146                                 close(tcpfd);
147                 }
148
149                 if (pollfds[TCP_SOCK6].revents) { /* New tcp connection */
150                         int tcpfd, flag = 1;
151                         uint32_t addrlen;
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)
157                                 close(tcpfd);
158                 }
159
160                 if (pollfds[UDP_SOCK].revents) {
161                         Client_read_udp(udpsocks[0]);
162                 }
163                 if (pollfds[UDP_SOCK6].revents) {
164                         Client_read_udp(udpsocks[1]);
165                 }
166                 for (i = 0; i < clientcount; i++) {
167                         if (pollfds[i + 4].revents & POLLIN) {
168                                 Client_read_fd(pollfds[i + 4].fd);
169                         }
170                         if (pollfds[i + 4].revents & POLLOUT) {
171                                 Client_write_fd(pollfds[i + 4].fd);
172                         }
173                 }
174         }
175 }
176
177 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
178 {
179         uint8_t yes = 1;
180         int error = 0;
181         int sockets[2];
182
183         /* IPv4 socket setup */
184         sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
185         if (sockets[0] < 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);
194
195         pollfds[TCP_SOCK].fd = sockets[0];
196         pollfds[TCP_SOCK].events = POLLIN;
197
198         /* IPv6 socket setup */
199         sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
200         if (sockets[1] < 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);
211
212         pollfds[TCP_SOCK6].fd = sockets[1];
213         pollfds[TCP_SOCK6].events = POLLIN;
214 }
215
216 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
217 {
218         uint8_t yes = 1;
219         int val = 0;
220         int error = 0;
221         int sockets[2];
222         char ipv6Representation[INET6_ADDRSTRLEN];
223
224         if((udpsocks = malloc(2 * sizeof(int))) == NULL)
225                 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
226
227         inet_ntop(AF_INET6, &((struct sockaddr_in6*)addresses[1])->sin6_addr, ipv6Representation, sizeof(INET6_ADDRSTRLEN));
228
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));
233         val = 0xe0;
234         if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
235                 Log_warn("Server: Failed to set TOS for UDP Socket");
236         val = 0x80;
237         if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
238                 Log_warn("Server: Failed to set TOS for UDP Socket");
239
240         fcntl(sockets[0], F_SETFL, O_NONBLOCK);
241         pollfds[UDP_SOCK].fd = sockets[0];
242         pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
243
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));
249         val = 0xe0;
250         if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
251                 Log_warn("Server: Failed to set TOS for UDP Socket");
252         val = 0x80;
253         if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
254                 Log_warn("Server: Failed to set TOS for UDP Socket");
255
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];
261 }
262
263 void Server_run()
264 {
265         struct pollfd *pollfds;
266
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");
270
271         /* Figure out bind address and port */
272         struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
273
274         /* Prepare TCP sockets */
275         Server_setupTCPSockets(addresses, pollfds);
276
277         /* Prepare UDP sockets */
278         Server_setupUDPSockets(addresses, pollfds);
279
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/");
283
284         /* Main server loop */
285         Server_runLoop(pollfds);
286
287         /* Disconnect clients and cleanup memory */
288         Client_disconnect_all();
289         free(pollfds);
290         free(addresses[0]);
291         free(addresses[1]);
292         free(addresses);
293         free(udpsocks);
294 }
295
296 void Server_shutdown()
297 {
298         shutdown_server = true;
299 }