diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..895b62a --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.swp +*.swo +build/ diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..736c83a --- /dev/null +++ b/build.sh @@ -0,0 +1,13 @@ +#!/usr/bin/bash + +# check if build directory exists +if [ -d build ]; then + echo "[I] build/ directory exists, deleting..." + rm -rf build +fi +# create build/ directory +mkdir build + +# build +echo "[I] Building ipoim..." +gcc *.c $(curl-config --cflags) $(curl-config --libs) -I. -o build/ipoim diff --git a/event_loop.c b/event_loop.c new file mode 100644 index 0000000..96c068b --- /dev/null +++ b/event_loop.c @@ -0,0 +1,63 @@ +#include "event_loop.h" + +#include + +#include +#include + +/* + * Macros + */ +#define MAX_EPOLL_EVENTS (20) + +/* + * Data + */ +static int _efd = -1; +static loop_cb_t _cb = NULL; +static struct epoll_event _evs[MAX_EPOLL_EVENTS]; + +/* + * Public API + */ +bool loop_init(loop_cb_t callback) { + _efd = epoll_create1(0); + if (_efd == -1) { + printf("[!] epoll_create1 failed: %d\n", errno); + return false; + } + _cb = callback; + return true; +} + +void loop_deinit() { + close(_efd); +} + +bool loop_ctl(int op, int fd, struct epoll_event *event) { + if (epoll_ctl(_efd, op, fd, event) == -1) { + printf("[!] epoll_ctl failed: %d\n", errno); + return false; + } + return true; +} + +bool loop_wait() { + int result = epoll_wait( + _efd, + _evs, + MAX_EPOLL_EVENTS, + -1 + ); + if (result < 0) { + printf("[!] epoll_wait failed: %d\n", errno); + return false; + } + if (!result) { + return true; + } + for (int i = 0; i < result; ++i) { + _cb(_evs[i].data.fd, _evs[i].events); + } + return true; +} diff --git a/event_loop.h b/event_loop.h new file mode 100644 index 0000000..8adf2b8 --- /dev/null +++ b/event_loop.h @@ -0,0 +1,59 @@ +#ifndef __EVENT_LOOP_H +#define __EVENT_LOOP_H + +#include +#include + +#include +#include + +/* + * Type definitions + */ +typedef void (*loop_cb_t)(int fd, uint32_t events); + +/* + * Public API + */ +// Initialize the event loop. +// Parameters: +// - callback - callback to use in loop_wait +// Returns: +// - true on success +// - false on failure +// Remarks: +// - must be called before event loop is used +bool loop_init(loop_cb_t callback); + +// Finalize the event loop. +// - must be called on app termination +void loop_deinit(); + +// Set callback for file descriptor event. +// Remarks: +// - this callback gets called in loop_wait +void loop_set_callback(loop_cb_t callback); + +// Call epoll_ctl. +// Parameters: +// - op - op +// - fd - fd +// - event - event +// Returns: +// - true on success +// - false on failure +// Remarks: +// - just calls epoll_ctl +bool loop_ctl(int op, int fd, struct epoll_event *event); + +// Call epoll_wait and process the events. +// Returns: +// - true on success +// - false on failure +// Remarks: +// - you should terminate the app if this function +// fails +bool loop_wait(); + + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..55c36f2 --- /dev/null +++ b/main.c @@ -0,0 +1,99 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include "event_loop.h" + +/* + * Data + */ +static bool _to_work = true; +static int _sig_fd = -1; + +/* + * Private API + */ +// Initialize signals. +// Returns: +// - true on success +// Remarks: +// - loop_init() must be called before this one +static bool signals_init() { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGQUIT); + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { + printf("[!] sigprocmask failed: %d\n", errno); + return false; + } + _sig_fd = signalfd( + -1, + &mask, + SFD_NONBLOCK + ); + if (_sig_fd == -1) { + printf("[!] signalfd failed: %d\n", errno); + return false; + } + struct epoll_event ev; + ev.data.fd = _sig_fd; + ev.events = EPOLLIN; + bool loop_res = loop_ctl( + EPOLL_CTL_ADD, + _sig_fd, + &ev + ); + if (!loop_res) { + close(_sig_fd); + printf("[!] loop_ctl failed\n"); + return false; + } + return true; +} + +static void signals_deinit() { + close(_sig_fd); +} + +/* + * Callbacks and main + */ +// This callback is called by loop_wait when event happens. +static void on_fd_event(int fd, uint32_t events) { + // Termination + if (fd == _sig_fd) { + _to_work = false; + } + else { + printf("[!] Event has happened on an unknown file descriptor\n"); + } +} + +int main(int argc, char **argv) { + if (!loop_init(on_fd_event)) { + return 1; + } + if (!signals_init()) { + loop_deinit(); + return 1; + } + + while (_to_work) { + if (!loop_wait()) { + printf("[!] loop_wait returns false, stopping...\n"); + break; + } + printf("--- loop ---\n"); + } + + signals_deinit(); + loop_deinit(); + return 0; +} diff --git a/utils.c b/utils.c new file mode 100644 index 0000000..e69de29 diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..4fe2741 --- /dev/null +++ b/utils.h @@ -0,0 +1,6 @@ +#ifndef __UTILS_H +#define __UTILS_H + + + +#endif