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 bool_t shutdown_server;
58 extern char *bindaddr;
59 extern char *bindaddr6;
65 /* Initialize the address structures for IPv4 and IPv6 */
66 struct sockaddr_storage** Server_setupAddressesAndPorts()
68 struct sockaddr_storage** addresses = malloc(2 * sizeof(void*));
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);
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!");
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!");
88 ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
89 ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport6) ? bindport6 : getIntConf(BINDPORT6));
91 addresses[0] = v4address;
92 addresses[1] = v6address;
97 void Server_runLoop(struct pollfd* pollfds)
99 int timeout = 1000, rc, clientcount;
101 etimer_t janitorTimer;
102 Timer_init(&janitorTimer);
104 while (!shutdown_server) {
105 struct sockaddr_storage remote;
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]);
114 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
117 Timer_restart(&janitorTimer);
118 timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
120 rc = poll(pollfds, clientcount + 4, timeout);
121 if (rc == 0) { /* Timeout */
123 Timer_restart(&janitorTimer);
128 if (errno == EINTR) /* signal */
131 Log_fatal("poll: error %d", errno);
133 if (pollfds[TCP_SOCK].revents) { /* New tcp connection */
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)
146 if (pollfds[TCP_SOCK6].revents) { /* New tcp connection */
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)
157 if (pollfds[UDP_SOCK].revents) {
158 Client_read_udp(udpsocks[0]);
160 if (pollfds[UDP_SOCK6].revents) {
161 Client_read_udp(udpsocks[1]);
163 for (i = 0; i < clientcount; i++) {
164 if (pollfds[i + 4].revents & POLLIN) {
165 Client_read_fd(pollfds[i + 4].fd);
167 if (pollfds[i + 4].revents & POLLOUT) {
168 Client_write_fd(pollfds[i + 4].fd);
175 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
181 /* IPv4 socket setup */
182 sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
184 Log_fatal("socket IPv4");
185 if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
186 Log_fatal("setsockopt IPv4: %s", strerror(errno));
187 if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
188 Log_fatal("bind IPv4: %s", strerror(errno));
189 if (listen(sockets[0], 3) < 0)
190 Log_fatal("listen IPv4");
191 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
193 pollfds[TCP_SOCK].fd = sockets[0];
194 pollfds[TCP_SOCK].events = POLLIN;
196 /* IPv6 socket setup */
197 sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
199 Log_fatal("socket IPv6");
200 if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
201 Log_fatal("setsockopt IPv6: %s", strerror(errno));
202 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
203 Log_fatal("setsockopt IPv6: %s", strerror(errno));
204 if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
205 Log_fatal("bind IPv6: %s", strerror(errno));
206 if (listen(sockets[1], 3) < 0)
207 Log_fatal("listen IPv6");
208 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
210 pollfds[TCP_SOCK6].fd = sockets[1];
211 pollfds[TCP_SOCK6].events = POLLIN;
214 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
220 char ipv6Representation[INET6_ADDRSTRLEN];
222 if((udpsocks = malloc(2 * sizeof(int))) == NULL)
223 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
225 inet_ntop(AF_INET6, &((struct sockaddr_in6*)addresses[1])->sin6_addr, ipv6Representation, sizeof(INET6_ADDRSTRLEN));
227 sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
228 if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
229 Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[0])->sin_port,
230 inet_ntoa(((struct sockaddr_in*)addresses[0])->sin_addr), strerror(errno));
232 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
233 Log_warn("Server: Failed to set TOS for UDP Socket");
235 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
236 Log_warn("Server: Failed to set TOS for UDP Socket");
238 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
239 pollfds[UDP_SOCK].fd = sockets[0];
240 pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
242 sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
243 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
244 Log_fatal("setsockopt IPv6: %s", strerror(errno));
245 if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
246 Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[1])->sin_port, ipv6Representation, strerror(errno));
248 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
249 Log_warn("Server: Failed to set TOS for UDP Socket");
251 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
252 Log_warn("Server: Failed to set TOS for UDP Socket");
254 fcntl(sockets[1], F_SETFL, O_NONBLOCK);
255 pollfds[UDP_SOCK6].fd = sockets[1];
256 pollfds[UDP_SOCK6].events = POLLIN | POLLHUP | POLLERR;
257 udpsocks[0] = sockets[0];
258 udpsocks[1] = sockets[1];
263 struct pollfd *pollfds;
265 /* max clients + listen sock + udp sock + client connecting that will be disconnected */
266 if ((pollfds = calloc((getIntConf(MAX_CLIENTS) + 5) , sizeof(struct pollfd))) == NULL)
267 Log_fatal("out of memory");
269 /* Figure out bind address and port */
270 struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
272 /* Prepare TCP sockets */
273 Server_setupTCPSockets(addresses, pollfds);
275 /* Prepare UDP sockets */
276 Server_setupUDPSockets(addresses, pollfds);
278 Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
279 UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
280 Log_info("Visit http://code.google.com/p/umurmur/");
282 /* Main server loop */
283 Server_runLoop(pollfds);
285 /* Disconnect clients and cleanup memory */
286 Client_disconnect_all();
293 void Server_shutdown()
295 shutdown_server = true;