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);
174 void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
180 /* IPv4 socket setup */
181 sockets[0] = socket(PF_INET, SOCK_STREAM, 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);
192 pollfds[TCP_SOCK].fd = sockets[0];
193 pollfds[TCP_SOCK].events = POLLIN;
195 /* IPv6 socket setup */
196 sockets[1] = socket(PF_INET6, SOCK_STREAM, 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);
209 pollfds[TCP_SOCK6].fd = sockets[1];
210 pollfds[TCP_SOCK6].events = POLLIN;
213 void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
219 char ipv6Representation[INET6_ADDRSTRLEN];
221 if((udpsocks = malloc(2 * sizeof(int))) == NULL)
222 Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
224 inet_ntop(AF_INET6, &((struct sockaddr_in6*)addresses[1])->sin6_addr, ipv6Representation, sizeof(INET6_ADDRSTRLEN));
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));
231 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
232 Log_warn("Server: Failed to set TOS for UDP Socket");
234 if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
235 Log_warn("Server: Failed to set TOS for UDP Socket");
237 fcntl(sockets[0], F_SETFL, O_NONBLOCK);
238 pollfds[UDP_SOCK].fd = sockets[0];
239 pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
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));
247 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
248 Log_warn("Server: Failed to set TOS for UDP Socket");
250 if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
251 Log_warn("Server: Failed to set TOS for UDP Socket");
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];
262 struct pollfd *pollfds;
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");
268 /* Figure out bind address and port */
269 struct sockaddr_storage** addresses = Server_setupAddressesAndPorts();
271 /* Prepare TCP sockets */
272 Server_setupTCPSockets(addresses, pollfds);
274 /* Prepare UDP sockets */
275 Server_setupUDPSockets(addresses, pollfds);
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/");
281 /* Main server loop */
282 Server_runLoop(pollfds);
284 /* Disconnect clients and cleanup memory */
285 Client_disconnect_all();
293 void Server_shutdown()
295 shutdown_server = true;