#ifndef foomainhfoo #define foomainhfoo #include #include struct cfg; #include "utils.h" extern struct cfg *cfg; extern bool exiting; extern unsigned debug_mask; enum debug_lvl { DBG_ERROR = (0x1 << 1), DBG_INFO = (0x1 << 2), DBG_VERBOSE = (0x1 << 3), DBG_CFG = (0x1 << 4), DBG_REF = (0x1 << 5), DBG_MALLOC = (0x1 << 6), DBG_ANN = (0x1 << 7), DBG_SIG = (0x1 << 8), DBG_UR = (0x1 << 9), DBG_SRV = (0x1 << 10), DBG_PROXY = (0x1 << 11), DBG_RCON = (0x1 << 12), DBG_IDLE = (0x1 << 13), DBG_IGMP = (0x1 << 14), DBG_SYSD = (0x1 << 15), DBG_DNS = (0x1 << 16), DBG_TIMER = (0x1 << 17), }; static inline bool debug_enabled(enum debug_lvl lvl) { return !!(lvl & debug_mask); } void __debug(enum debug_lvl lvl, const char *fmt, ...) __attribute__((format(printf, 2, 3))); #define __ifdebug(lvl, fmt, ...) \ do { \ if (debug_enabled((lvl))) \ __debug((lvl), fmt "\n"__VA_OPT__(,) __VA_ARGS__); \ } while (0) #define debug(lvl, fmt, ...) __ifdebug((lvl), "%s:%s:%i: " fmt, \ __FILE__, __func__, __LINE__ \ __VA_OPT__(,) __VA_ARGS__) #define verbose(fmt, ...) __ifdebug(DBG_VERBOSE, fmt, __VA_ARGS__) #define info(fmt, ...) __ifdebug(DBG_INFO, fmt, __VA_ARGS__) #define error(fmt, ...) __ifdebug(DBG_ERROR, "%s:%s:%i: " fmt, \ __FILE__, __func__, __LINE__ \ __VA_OPT__(,) __VA_ARGS__) void __die(const char *fmt, ...) __attribute__((format(printf, 1, 2))); #define die(fmt, ...) \ __die("%s:%s:%i: " fmt "\n", \ __FILE__, __func__, __LINE__ \ __VA_OPT__(,) __VA_ARGS__) #define assert_log(expr, msg) \ ((expr) ? \ (true) : \ (__debug(DBG_ERROR, "%s:%s:%i: assertion \"" msg "\" failed\n", \ __FILE__, __func__, __LINE__), false)) #define assert_return(expr, ...) \ do { \ if (!assert_log(expr, #expr)) \ return __VA_ARGS__; \ } while (0) #define assert_return_silent(expr, ...) \ do { \ if (!(expr)) \ return __VA_ARGS__; \ } while (0) #define assert_die(expr, msg) \ do { \ if (!assert_log(expr, #expr)) \ die(msg); \ } while (0) #define assert_task_alive_or(lvl, t, cmd) \ do { \ if (!(t)) { \ error("invalid task"); \ cmd; \ } \ \ if ((t)->dead) { \ debug((lvl), "task dead"); \ cmd; \ } \ } while(0) #define assert_task_alive(lvl, t) assert_task_alive_or((lvl), (t), return) void dump_tree(); struct uring_task; /* To save typing in all the function definitions below */ typedef void (*utask_cb_t)(struct uring_task *, int res); typedef int (*rutask_cb_t)(struct uring_task *, int res); struct uring_task_buf { char buf[4096]; size_t len; size_t done; struct iovec iov; struct msghdr msg; }; struct uring_task { const char *name; unsigned refcount; int fd; struct uring_task *parent; void (*free)(struct uring_task *); bool dead; struct uring_task_buf *tbuf; /* called once or repeatedly until is_complete_cb is satisfied */ utask_cb_t cb; /* returns: 0 = not complete; < 0 = error; > 0 = complete */ rutask_cb_t is_complete_cb; /* called once tbuf processing is done */ utask_cb_t final_cb; /* used for recvmsg/sendmsg */ struct saddr saddr; void *priv; }; struct cfg { /* Options */ uid_t uid; gid_t gid; const char *cfg_dir; const char *cfg_file; bool do_igmp; char *igmp_iface; bool splice_supported; uint16_t announce_interval; uint16_t proxy_connection_interval; uint16_t proxy_connection_attempts; bool socket_defer; bool socket_freebind; bool socket_keepalive; bool socket_iptos; bool socket_nodelay; /* Bookkeeping */ struct uring_ev *uring; struct server_cfg_monitor *server_cfg_monitor; struct signal_ev *signal; struct announce *announce; struct ptimer *ptimer; struct igmp *igmp; struct idle *idle; struct sd_bus *sd_bus; bool sd_bus_failed; struct uring_task task; struct list_head servers; }; #endif