+extern int bindport6;
+
+struct sockaddr_storage** Server_setupAddressesAndPorts()
+{
+ struct sockaddr_storage** addresses;
+
+ struct sockaddr_storage* v4address = calloc(1, sizeof(struct sockaddr_storage));
+ v4address->ss_family = AF_INET;
+ v4address->ss_len = sizeof(struct sockaddr_storage);
+ struct sockaddr_storage* v6address = calloc(1, sizeof(struct sockaddr_storage));
+ v6address->ss_family = AF_INET;
+ v6address->ss_len = sizeof(struct sockaddr_storage);
+
+ int error = 0;
+
+ error = inet_pton(AF_INET, (!bindaddr) ? ((getStrConf(BINDADDR)) ? getStrConf(BINDADDR) : "0.0.0.0")
+ : bindaddr, &(((struct sockaddr_in*)v4address)->sin_addr));
+ if (error == 0) Log_fatal("Invalid IPv4 address supplied!");
+
+ error = inet_pton(AF_INET, (!bindaddr6) ? ((getStrConf(BINDADDR6)) ? getStrConf(BINDADDR6) : "::")
+ : bindaddr6, &(((struct sockaddr_in6*)v6address)->sin6_addr));
+ if (error == 0) Log_fatal("Invalid IPv6 address supplied!");
+
+ ((struct sockaddr_in*)v4address)->sin_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
+ ((struct sockaddr_in6*)v6address)->sin6_port = htons((bindport) ? bindport : getIntConf(BINDPORT));
+
+ addresses[0] = v4address;
+ addresses[1] = v6address;
+
+ return addresses;
+}
+
+void Server_runLoop(struct pollfd* pollfds)
+ {
+ int timeout = 1000, rc, clientcount;
+ etimer_t janitorTimer;
+
+ Timer_init(&janitorTimer);
+
+ while (!shutdown_server) {
+ struct sockaddr_in remote;
+ int i;
+
+ pollfds[UDP_SOCK].revents = 0;
+ pollfds[TCP_SOCK].revents = 0;
+ clientcount = Client_getfds(&pollfds[2]);
+
+ timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
+ if (timeout <= 0) {
+ Client_janitor();
+ Timer_restart(&janitorTimer);
+ timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
+ }
+ rc = poll(pollfds, clientcount + 2, timeout);
+ if (rc == 0) { /* Timeout */
+ /* Do maintenance */
+ Timer_restart(&janitorTimer);
+ Client_janitor();
+ continue;
+ }
+ if (rc < 0) {
+ if (errno == EINTR) /* signal */
+ continue;
+ else
+ Log_fatal("poll: error %d", errno);
+ }
+ if (pollfds[LISTEN_SOCK].revents) { /* New tcp connection */
+ int tcpfd, flag = 1;
+ uint32_t addrlen;
+ addrlen = sizeof(struct sockaddr_in);
+ tcpfd = accept(pollfds[LISTEN_SOCK].fd, (struct sockaddr*)&remote, &addrlen);
+ fcntl(tcpfd, F_SETFL, O_NONBLOCK);
+ setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
+ Log_debug("Connection from %s port %d\n", inet_ntoa(remote.sin_addr),
+ ntohs(remote.sin_port));
+ if (Client_add(tcpfd, &remote) < 0)
+ close(tcpfd);
+ }
+
+ if (pollfds[UDP_SOCK].revents) {
+ Client_read_udp();
+ }
+ for (i = 0; i < clientcount; i++) {
+ if (pollfds[i + 2].revents & POLLIN) {
+ Client_read_fd(pollfds[i + 2].fd);
+ }
+ if (pollfds[i + 2].revents & POLLOUT) {
+ Client_write_fd(pollfds[i + 2].fd);
+ }
+ }
+ }
+ }