1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#ifndef foomainhfoo
#define foomainhfoo
#include <sys/socket.h>
#include <netinet/ip.h>
struct cfg;
#include "utils.h"
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 << 7),
DBG_UR = (0x1 << 8),
DBG_SRV = (0x1 << 9),
DBG_PROXY = (0x1 << 10),
DBG_RCON = (0x1 << 11),
DBG_IDLE = (0x1 << 12),
DBG_IGMP = (0x1 << 13),
DBG_SYSD = (0x1 << 14),
DBG_DNS = (0x1 << 15),
};
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_task_alive_or(lvl, t, cmd) \
do { \
if (!(t)) { \
error("invalid task\n"); \
cmd; \
} \
\
if ((t)->dead) { \
debug((lvl), "task dead\n"); \
cmd; \
} \
} while(0)
#define assert_task_alive(lvl, t) assert_task_alive_or((lvl), (t), return)
struct uring_task;
/* To save typing in all the function definitions below */
typedef void (*utask_cb_t)(struct cfg *, struct uring_task *, int res);
typedef int (*rutask_cb_t)(struct cfg *, 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 {
uid_t uid;
gid_t gid;
const char *homedir;
char *cfg_path;
bool do_igmp;
char *igmp_iface;
struct uring_ev *uev;
struct inotify_ev *iev;
struct signalfd_ev *sev;
struct announce *aev;
struct igmp *igmp;
struct sd_bus *sd_bus;
bool sd_bus_failed;
struct uring_task task;
struct list_head servers;
};
#endif
|