+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);
+ }
+ }
+ }
+ }
+