Indentation fixed
[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         v4address->ss_len = sizeof(struct sockaddr_storage);
73         struct sockaddr_storage* v6address = calloc(1, sizeof(struct sockaddr_storage));
74         v6address->ss_family = AF_INET6;
75         v6address->ss_len = sizeof(struct sockaddr_storage);
76
77         int error = 0;
78
79         const char* confadd = getStrConf(BINDADDR);
80         error = inet_pton(AF_INET, (!bindaddr) ? ((getStrConf(BINDADDR)) ? getStrConf(BINDADDR) : "0.0.0.0")
81                 : bindaddr, &(((struct sockaddr_in*)v4address)->sin_addr));
82         if (error == 0) Log_fatal("Invalid IPv4 address supplied!");
83
84         error = inet_pton(AF_INET6, (!bindaddr6) ? ((getStrConf(BINDADDR6)) ? getStrConf(BINDADDR6) : "::")
85                 : bindaddr6, &(((struct sockaddr_in6*)v6address)->sin6_addr));
86         if (error == 0) Log_fatal("Invalid IPv6 address supplied!");
87
88         ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
89         ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
90
91         addresses[0] = v4address;
92         addresses[1] = v6address;
93
94         return addresses;
95 }
96
97 void Server_runLoop(struct pollfd* pollfds)
98 {
99         int timeout = 1000, rc, clientcount;
100
101         etimer_t janitorTimer;
102         Timer_init(&janitorTimer);
103
104         while (!shutdown_server) {
105                 struct sockaddr_storage remote;
106                 int i;
107
108                 pollfds[UDP_SOCK].revents = 0;
109                 pollfds[UDP_SOCK6].revents = 0;
110                 pollfds[TCP_SOCK].revents = 0;
111                 pollfds[TCP_SOCK6].revents = 0;
112                 clientcount = Client_getfds(&pollfds[4]);
113
114                 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
115                 if (timeout <= 0) {
116                         Client_janitor();
117                         Timer_restart(&janitorTimer);
118                         timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
119                 }
120                 rc = poll(pollfds, clientcount + 4, timeout);
121                 if (rc == 0) { /* Timeout */
122                         /* Do maintenance */
123                         Timer_restart(&janitorTimer);
124                         Client_janitor();
125                         continue;
126                 }
127                 if (rc < 0) {
128                         if (errno == EINTR) /* signal */
129                                 continue;
130                         else
131                                 Log_fatal("poll: error %d", errno);
132                 }
133                 if (pollfds[TCP_SOCK].revents) { /* New tcp connection */
134                         int tcpfd, flag = 1;
135                         uint32_t addrlen;
136                         addrlen = sizeof(struct sockaddr_in);
137                         tcpfd = accept(pollfds[TCP_SOCK].fd, (struct sockaddr*)&remote, &addrlen);
138                         fcntl(tcpfd, F_SETFL, O_NONBLOCK);
139                         setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
140                         Log_debug("Connection from %s port %d\n", inet_ntoa(((struct sockaddr_in*)&remote)->sin_addr),
141                                 ntohs(((struct sockaddr_in*)&remote)->sin_port));
142                         if (Client_add(tcpfd, &remote) < 0)
143                                 close(tcpfd);
144                 }
145
146                 if (pollfds[TCP_SOCK6].revents) { /* New tcp connection */
147                         int tcpfd, flag = 1;
148                         uint32_t addrlen;
149                         addrlen = sizeof(struct sockaddr_in6);
150                         tcpfd = accept(pollfds[TCP_SOCK6].fd, (struct sockaddr*)&remote, &addrlen);
151                         fcntl(tcpfd, F_SETFL, O_NONBLOCK);
152                         setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
153                         if (Client_add(tcpfd, &remote) < 0)
154                                 close(tcpfd);
155                 }
156
157                 if (pollfds[UDP_SOCK].revents) {
158                         Client_read_udp(udpsocks[0]);
159                 }
160                 if (pollfds[UDP_SOCK6].revents) {
161                         Client_read_udp(udpsocks[1]);
162                 }
163                 for (i = 0; i < clientcount; i++) {
164                         if (pollfds[i + 4].revents & POLLIN) {
165                                 Client_read_fd(pollfds[i + 4].fd);
166                         }
167                         if (pollfds[i + 4].revents & POLLOUT) {
168                                 Client_write_fd(pollfds[i + 4].fd);
169                         }
170                 }
171         }
172 }
173
174 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
175 {
176         uint8_t yes = 1;
177         int error = 0;
178         int sockets[2];
179
180         /* IPv4 socket setup */
181         sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
182         if (sockets[0] < 0)
183                 Log_fatal("socket IPv4");
184         if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
185                 Log_fatal("setsockopt IPv4: %s", strerror(errno));
186         if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
187                 Log_fatal("bind IPv4: %s", strerror(errno));
188         if (listen(sockets[0], 3) < 0)
189                 Log_fatal("listen IPv4");
190         fcntl(sockets[0], F_SETFL, O_NONBLOCK);
191
192         pollfds[TCP_SOCK].fd = sockets[0];
193         pollfds[TCP_SOCK].events = POLLIN;
194
195         /* IPv6 socket setup */
196         sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
197         if (sockets[1] < 0)
198                 Log_fatal("socket IPv6");
199         if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
200                 Log_fatal("setsockopt IPv6: %s", strerror(errno));
201         if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
202                 Log_fatal("setsockopt IPv6: %s", strerror(errno));
203         if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
204                 Log_fatal("bind IPv6: %s", strerror(errno));
205         if (listen(sockets[1], 3) < 0)
206                 Log_fatal("listen IPv6");
207         fcntl(sockets[1], F_SETFL, O_NONBLOCK);
208
209         pollfds[TCP_SOCK6].fd = sockets[1];
210         pollfds[TCP_SOCK6].events = POLLIN;
211 }
212
213 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
214 {
215         uint8_t yes = 1;
216         int val = 0;
217         int error = 0;
218         int sockets[2];
219         char ipv6Representation[INET6_ADDRSTRLEN];
220
221         if((udpsocks = malloc(2 * sizeof(int))) == NULL)
222                 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
223
224         inet_ntop(AF_INET6, &((struct sockaddr_in6*)addresses[1])->sin6_addr, ipv6Representation, sizeof(INET6_ADDRSTRLEN));
225
226         sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
227         if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
228                 Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[0])->sin_port,
229                         inet_ntoa(((struct sockaddr_in*)addresses[0])->sin_addr), strerror(errno));
230         val = 0xe0;
231         if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
232                 Log_warn("Server: Failed to set TOS for UDP Socket");
233         val = 0x80;
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
237         fcntl(sockets[0], F_SETFL, O_NONBLOCK);
238         pollfds[UDP_SOCK].fd = sockets[0];
239         pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
240
241         sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
242         if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
243                 Log_fatal("setsockopt IPv6: %s", strerror(errno));
244         if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
245                 Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[1])->sin_port, ipv6Representation, strerror(errno));
246         val = 0xe0;
247         if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
248                 Log_warn("Server: Failed to set TOS for UDP Socket");
249         val = 0x80;
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
253         fcntl(sockets[1], F_SETFL, O_NONBLOCK);
254         pollfds[UDP_SOCK6].fd = sockets[1];
255         pollfds[UDP_SOCK6].events = POLLIN | POLLHUP | POLLERR;
256         udpsocks[0] = sockets[0];
257         udpsocks[1] = sockets[1];
258 }
259
260 void Server_run()
261 {
262         struct pollfd *pollfds;
263
264         /* max clients + listen sock + udp sock + client connecting that will be disconnected */
265         if ((pollfds = calloc((getIntConf(MAX_CLIENTS) + 5) , sizeof(struct pollfd))) == NULL)
266                 Log_fatal("out of memory");
267
268         /* Figure out bind address and port */
269         struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
270
271         /* Prepare TCP sockets */
272         Server_setupTCPSockets(addresses, pollfds);
273
274         /* Prepare UDP sockets */
275         Server_setupUDPSockets(addresses, pollfds);
276
277         Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
278                 UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
279         Log_info("Visit http://code.google.com/p/umurmur/");
280
281         /* Main server loop */
282         Server_runLoop(pollfds);
283
284         /* Disconnect clients and cleanup memory */
285         Client_disconnect_all();
286         free(pollfds);
287         free(addresses[0]);
288         free(addresses[1]);
289         free(addresses);
290         free(udpsocks);
291 }
292
293 void Server_shutdown()
294 {
295         shutdown_server = true;
296 }