Skip to content
Snippets Groups Projects
Commit 67eabc0b authored by Christian Dietrich's avatar Christian Dietrich
Browse files

Dec 12 -- Santa's Postbox

Article:  https://ibr.cs.tu-bs.de/advent/12-postbox/
Workload: ~74 source-code lines
parent ed92332a
No related branches found
No related tags found
No related merge requests found
PROG = postbox
DEPS = postbox.c fifo.c domain.c
${PROG}: ${DEPS}
gcc ${PROG}.c -o $@ -Wall -g -lrt
run: ${PROG}
./${PROG}
strace: ${PROG}
strace ./${PROG}
clean:
rm -f ./${PROG}
int domain_prepare(int epoll_fd) {
printf("... by socket: echo 2 | nc -U socket\n");
return -1;
}
void domain_accept(int epoll_fd, int sock_fd, int events) {
}
void domain_recv(int epoll_fd, int sock_fd, int events) {
}
int fifo_prepare(int epoll_fd) {
printf("... by fifo: echo 1 > fifo\n");
return -1;
}
void fifo_handle(int epoll_fd, int fifo_fd, int events) {
}
#define _GNU_SOURCE
#include <stdio.h>
#include <time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <assert.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <mqueue.h>
#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while(0)
// Adds a file descriptor to an open epoll instance's list of
// interesting file descriptors.
//// events - For which events are we waiting (usually EPOLLIN)
//// data - The kernel returns this data when an event occurs
void epoll_add(int epoll_fd, int fd, int events) {
struct epoll_event ev;
ev.events = events;
ev.data.fd = fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
die("epoll_ctl: activate");
}
}
// Remove a file descriptor from the interest list.
void epoll_del(int epoll_fd, int fd) {
if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1) {
die("epoll_ctl: reset");
}
}
#include "fifo.c"
#include "domain.c"
struct postbox {
int fd;
int (*prepare)(int epoll_fd);
void (*handle)(int epoll_fd, int fd, int events);
};
struct postbox boxes[] = {
{-1, fifo_prepare, fifo_handle},
{-1, domain_prepare, domain_accept},
// This must be the last entry
{-1, NULL, domain_recv}, // Fallback
};
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
int main() {
int epoll_fd = epoll_create1(0);
if (epoll_fd == -1)
die("epoll_create");
printf("Santas Postbox is open! Send your requests ...\n");
// Initialize all backends by calling the prepare method
for (int i = 0; i < ARRAY_SIZE(boxes); i++) {
if (boxes[i].prepare) {
boxes[i].fd = boxes[i].prepare(epoll_fd);
}
}
while (true) {
// We use epoll_wait(2) to wait for at least one event, but we
// can receive up to ten events. We do not set a timeout but
// wait forever if necessary.
struct epoll_event event[10];
int nfds = epoll_wait(epoll_fd, event, 10, -1);
for (int n = 0; n < nfds; n++) {
int fd = event[n].data.fd;
for (int i = 0; i < ARRAY_SIZE(boxes); i++) {
if (boxes[i].fd == fd || boxes[i].fd == -1) {
boxes[i].handle(epoll_fd, fd, event[n].events);
break;
}
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment