#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
+#include <sys/timerfd.h>
#include <unistd.h>
#include "logging.h"
unsigned int connections;
};
+static int dump_stats(struct fireperf_config* conf, const struct fireperf_server_stats* stats) {
+ DEBUG(conf, "Printing statistics...\n");
+
+ return 0;
+}
+
static int create_socket(struct fireperf_config* conf) {
// Open a new socket
int fd = socket(AF_INET6, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
goto ERROR;
}
+ // Create timerfd() to print statistics
+ int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
+ if (timerfd < 0) {
+ ERROR(conf, "timerfd_create() failed: %s\n", strerror(errno));
+ goto ERROR;
+ }
+
+ ev.events = EPOLLIN;
+ ev.data.fd = timerfd;
+
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev)) {
+ ERROR(conf, "Could not add timerfd to epoll(): %s\n",
+ strerror(errno));
+ goto ERROR;
+ }
+
+ // Let the timer ping us once a second
+ struct itimerspec timer = {
+ .it_interval.tv_sec = 1,
+ .it_value.tv_sec = 1,
+ };
+
+ r = timerfd_settime(timerfd, 0, &timer, NULL);
+ if (r) {
+ ERROR(conf, "Could not set timer: %s\n", strerror(errno));
+ return 1;
+ }
+
DEBUG(conf, "Entering main loop...\n");
while (!conf->terminated) {
// A connection has been opened
stats.connections++;
- continue;
- }
- // Handle any connection events (like disconnects)
- if (ev.events & EPOLLHUP) {
- DEBUG(conf, "Connection %d has closed\n", fd);
+ // Handle timer events
+ } else if (fd == timerfd) {
+ uint64_t expirations;
- // Remove the file descriptor from epoll()
- if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL)) {
- ERROR(conf, "Could not remove socket file descriptfor from epoll(): %s\n",
- strerror(errno));
+ // Read from the timer to disarm it
+ ssize_t bytes_read = read(timerfd, &expirations, sizeof(expirations));
+ if (bytes_read <= 0) {
+ ERROR(conf, "Could not read from timerfd: %s\n", strerror(errno));
+ goto ERROR;
}
- // Free up any resources
- close(fd);
+ r = dump_stats(conf, &stats);
+ if (r)
+ goto ERROR;
- // This connection is now closed
- stats.connections--;
+ // Handle any connection events
+ } else {
+ if (ev.events & EPOLLHUP) {
+ DEBUG(conf, "Connection %d has closed\n", fd);
- // Skip processing anything else, because it would be pointless
- continue;
- }
+ // Remove the file descriptor from epoll()
+ if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL)) {
+ ERROR(conf, "Could not remove socket file descriptfor from epoll(): %s\n",
+ strerror(errno));
+ }
- // One of the connections had IO
- if (ev.events & EPOLLIN) {
- r = handle_io_on_connection(conf, fd);
- if (r < 0)
- goto ERROR;
+ // Free up any resources
+ close(fd);
+
+ // This connection is now closed
+ stats.connections--;
+
+ // Skip processing anything else, because it would be pointless
+ continue;
+ }
+
+ // One of the connections had IO
+ if (ev.events & EPOLLIN) {
+ r = handle_io_on_connection(conf, fd);
+ if (r < 0)
+ goto ERROR;
+ }
}
}
}
if (epollfd > 0)
close(epollfd);
+ if (timerfd > 0)
+ close(timerfd);
+
return r;
}