/* * Copyright (C) 2013 Martin Willi * Copyright (C) 2013 revosec AG * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup watcher watcher * @{ @ingroup processor */ #ifndef WATCHER_H_ #define WATCHER_H_ typedef struct watcher_t watcher_t; typedef enum watcher_event_t watcher_event_t; typedef enum watcher_state_t watcher_state_t; #include /** * Callback function to register for file descriptor events. * * The callback is executed asynchronously using a thread from the pool. * Monitoring of fd is temporarily suspended to avoid additional events while * it is processed asynchronously. To allow concurrent events, one can quickly * process it (using a read/write) and return from the callback. This will * re-enable the event, while the data read can be processed in another * asynchronous job. * * On Linux, even if select() marks an FD as "ready", a subsequent read/write * can block. It is therefore highly recommended to use non-blocking I/O * and handle EAGAIN/EWOULDBLOCK gracefully. * * @param data user data passed during registration * @param fd file descriptor the event occurred on * @param event type of event * @return TRUE to keep watching event, FALSE to unregister fd for event */ typedef bool (*watcher_cb_t)(void *data, int fd, watcher_event_t event); /** * What events to watch for a file descriptor. */ enum watcher_event_t { WATCHER_READ = (1<<0), WATCHER_WRITE = (1<<1), WATCHER_EXCEPT = (1<<2), }; /** * State the watcher currently is in */ enum watcher_state_t { /** no watcher thread running or queued */ WATCHER_STOPPED = 0, /** a job has been queued for watching, but not yet started */ WATCHER_QUEUED, /** a watcher thread is active, dispatching socket events */ WATCHER_RUNNING, }; /** * Watch multiple file descriptors using select(). */ struct watcher_t { /** * Start watching a new file descriptor. * * Multiple callbacks can be registered for the same file descriptor, and * all of them get notified. Such callbacks are executed concurrently. * * @param fd file descriptor to start watching * @param events ORed set of events to watch * @param cb callback function to invoke on events * @param data data to pass to cb() */ void (*add)(watcher_t *this, int fd, watcher_event_t events, watcher_cb_t cb, void *data); /** * Stop watching a previously registered file descriptor. * * This call blocks until any active callback for this FD returns. All * callbacks registered for that FD get unregistered. * * @param fd file descriptor to stop watching */ void (*remove)(watcher_t *this, int fd); /** * Get the current watcher state * * @return currently active watcher state */ watcher_state_t (*get_state)(watcher_t *this); /** * Destroy a watcher_t. */ void (*destroy)(watcher_t *this); }; /** * Create a watcher instance. * * @return watcher */ watcher_t *watcher_create(); #endif /** WATCHER_H_ @}*/