29 #include <netinet/in.h>
30 #include <sys/epoll.h>
40 #define MAX_EPOLL_EVENTS 512
43 struct epoll_event event;
44 memset(&event, 0,
sizeof(event));
45 event.data.fd = new_fd;
46 event.events = events | EPOLLONESHOT;
48 int rtn = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, new_fd, &event);
51 log(LOG_EPOLL_OPS,
"failed to enable fd %d on epoll %d: %s",
52 new_fd, epoll_fd, strerror(errno));
55 log(LOG_EPOLL_OPS,
"enabled fd %d on epoll", new_fd);
60 struct epoll_event event;
61 memset(&event, 0,
sizeof(event));
62 event.data.fd = new_fd;
64 event.events = events | EPOLLONESHOT;
66 event.events = events;
69 int rtn = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_fd, &event);
72 log(LOG_EPOLL_OPS,
"failed to add fd %d on epoll %d: %s",
73 new_fd, epoll_fd, strerror(errno));
76 log(LOG_EPOLL_OPS,
"Added fd %d to epoll", new_fd);
89 log(LOG_EPOLL_OPS,
"Accepting a new connection");
91 struct sockaddr_in client_addr;
92 socklen_t addr_len =
sizeof(client_addr);
94 int new_fd = accept(socketfd, (
struct sockaddr*) &client_addr, &addr_len);
96 log_perror(
"Error accepting new connection from socket handler");
102 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
103 rtn = getnameinfo((
struct sockaddr*)&client_addr, addr_len,
106 NI_NUMERICHOST| NI_NUMERICSERV);
108 log(LOG_EPOLL_OPS,
"Accepted connection on descriptor %d"
115 int flags = O_NONBLOCK;;
116 rtn = fcntl(new_fd, F_SETFL, flags);
133 int (*connection_handler)(
int,
void*),
134 int (*accept_handler)(
int,
void*),
136 struct epoll_event events[MAX_EPOLL_EVENTS];
138 for (
int j=0; j<batch_size || batch_size == -1; j++) {
139 log(LOG_EPOLL_OPS,
"Waiting on epoll");
140 int n = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS, timeout);
144 log(LOG_EPOLL_OPS,
"Epoll returned %d events", n);
145 for (
int i=0; i < n; ++i) {
146 if (socket_fd == events[i].data.fd) {
147 log(LOG_EPOLL_OPS,
"Accepting connection on %d", socket_fd);
153 if (accept_handler) {
154 accept_handler(new_fd, data);
156 log(LOG_EPOLL_OPS,
"Accepted new connection");
159 log(LOG_EPOLL_OPS,
"Processing connection (fd: %d)",
161 int rtn = connection_handler(events[i].data.fd, data);
164 log_error(
"Failed processing existing connection (fd: %d)",
167 log(LOG_EPOLL_OPS,
"Got exit code %d from fd %d",
168 rtn, events[i].data.fd);
172 log(LOG_EPOLL_OPS,
"Processed connection (fd: %d)",
183 int epoll_fd = epoll_create1(0);
184 if (epoll_fd == -1) {
190 struct epoll_event event;
191 memset(&event, 0,
sizeof(event));
192 event.data.fd = socket_fd;
193 event.events = EPOLLIN;
195 if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &event) == -1) {
196 log_perror(
"epoll_ctl() failed to add socket");
201 log(LOG_EPOLL_OPS,
"Created epoll fd %d",epoll_fd);
Wrapper functions for epoll to manage event-based communication.
int epoll_fd
The epoll file descriptor monitoring sockets.
#define log_perror(fmt,...)
Logging of status messages to the terminal.
int add_to_epoll(int epoll_fd, int new_fd, uint32_t events, bool oneshot)
Adds a file descriptor to an epoll instance.
int init_epoll(int socket_fd)
Initializes a new instance of an epoll file descriptor and adds a socket to it, listening for input o...
#define log_error(fmt,...)
int enable_epoll(int epoll_fd, int new_fd, uint32_t events)
Enables a file descriptor which has already been aded to an epoll instance.
static int accept_new_connection(int socketfd, int epoll_fd, int oneshot)
Accepts a new connection and adds it to the epoll instance.
int epoll_loop(int socket_fd, int epoll_fd, int batch_size, int timeout, bool oneshot, int(*connection_handler)(int, void *), int(*accept_handler)(int, void *), void *data)
The event-based loop for epoll_wait.
#define log(level, fmt,...)
Log at a custom level.