ustream: prevent recursive calls to the read callback
[project/libubox.git] / udebug.h
1 /*
2 * udebug - debug ring buffer library
3 *
4 * Copyright (C) 2023 Felix Fietkau <nbd@nbd.name>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #ifndef __UDEBUG_RINGBUF_H
19 #define __UDEBUG_RINGBUF_H
20
21 #include <sys/types.h>
22 #include <stdint.h>
23 #include <stdarg.h>
24
25 #include "list.h"
26 #include "uloop.h"
27 #include "avl.h"
28
29 #define UDEBUG_SOCK_NAME "/var/run/udebug.sock"
30
31 enum udebug_format {
32 UDEBUG_FORMAT_PACKET,
33 UDEBUG_FORMAT_STRING,
34 UDEBUG_FORMAT_BLOBMSG,
35 };
36
37 enum {
38 UDEBUG_DLT_ETHERNET = 1,
39 UDEBUG_DLT_PPP = 50,
40 UDEBUG_DLT_RAW_IP = 101,
41 UDEBUG_DLT_IEEE_802_11 = 105,
42 UDEBUG_DLT_IEEE_802_11_RADIOTAP = 127,
43 UDEBUG_DLT_NETLINK = 253,
44 };
45
46 enum udebug_meta_type {
47 UDEBUG_META_IFACE_NAME,
48 UDEBUG_META_IFACE_DESC,
49 __UDEBUG_META_MAX
50 };
51
52 #define UDEBUG_TS_MSEC 1000ULL
53 #define UDEBUG_TS_SEC (1000ULL * UDEBUG_TS_MSEC)
54
55 struct udebug;
56 struct udebug_hdr;
57
58 struct udebug_buf_flag {
59 const char *name;
60 uint64_t mask;
61 };
62
63 struct udebug_buf_meta {
64 const char *name;
65 enum udebug_format format;
66 uint32_t sub_format; /* linktype for UDEBUG_FORMAT_PACKET */
67 const struct udebug_buf_flag *flags;
68 unsigned int n_flags;
69 };
70
71 struct udebug_buf {
72 struct udebug *ctx;
73 const struct udebug_buf_meta *meta;
74 uint32_t id;
75
76 struct list_head list;
77
78 struct udebug_hdr *hdr;
79 void *data;
80 size_t data_size;
81 size_t head_size;
82 size_t ring_size;
83 int fd;
84 };
85
86 struct udebug_packet_info {
87 const char *attr[__UDEBUG_META_MAX];
88 };
89
90 struct udebug_remote_buf {
91 struct avl_node node;
92 struct udebug_buf buf;
93 bool poll;
94 uint32_t head;
95
96 /* provided by user */
97 uint32_t pcap_iface;
98 void *priv;
99 const struct udebug_packet_info *meta;
100 };
101
102 struct udebug {
103 struct list_head local_rings;
104 struct avl_tree remote_rings;
105 uint32_t next_id;
106 struct uloop_fd fd;
107 int poll_handle;
108 char *socket_path;
109 struct uloop_timeout reconnect;
110
111 /* filled by user */
112 void (*notify_cb)(struct udebug *ctx, struct udebug_remote_buf *rb);
113 };
114
115 struct udebug_ptr {
116 uint32_t start;
117 uint32_t len;
118 uint64_t timestamp;
119 };
120
121 struct udebug_snapshot {
122 struct udebug_ptr *entries;
123 unsigned int n_entries;
124 unsigned int dropped;
125 void *data;
126 size_t data_size;
127
128 uint32_t iter_idx;
129
130 enum udebug_format format;
131 uint32_t sub_format;
132
133 uint32_t rbuf_idx;
134 };
135
136 struct udebug_iter {
137 struct udebug_snapshot **list;
138 size_t n;
139
140 struct udebug_snapshot *s;
141 unsigned int s_idx;
142
143 uint64_t timestamp;
144 void *data;
145 size_t len;
146 };
147
148 uint64_t udebug_timestamp(void);
149
150 void udebug_entry_init_ts(struct udebug_buf *buf, uint64_t timestamp);
151 static inline void udebug_entry_init(struct udebug_buf *buf)
152 {
153 udebug_entry_init_ts(buf, udebug_timestamp());
154 }
155 void *udebug_entry_append(struct udebug_buf *buf, const void *data, uint32_t len);
156 int udebug_entry_printf(struct udebug_buf *buf, const char *fmt, ...)
157 __attribute__ ((format (printf, 2, 3)));
158 int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap)
159 __attribute__ ((format (printf, 2, 0)));
160 uint16_t udebug_entry_trim(struct udebug_buf *buf, uint16_t len);
161 void udebug_entry_set_length(struct udebug_buf *buf, uint16_t len);
162 void udebug_entry_add(struct udebug_buf *buf);
163
164 int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size);
165 int udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf,
166 const struct udebug_buf_meta *meta);
167 uint64_t udebug_buf_flags(struct udebug_buf *buf);
168 void udebug_buf_free(struct udebug_buf *buf);
169 static inline bool udebug_buf_valid(struct udebug_buf *buf)
170 {
171 return buf->hdr;
172 }
173
174 struct udebug_remote_buf *udebug_remote_buf_get(struct udebug *ctx, uint32_t id);
175 int udebug_remote_buf_map(struct udebug *ctx, struct udebug_remote_buf *rb, uint32_t id);
176 void udebug_remote_buf_unmap(struct udebug *ctx, struct udebug_remote_buf *rb);
177 int udebug_remote_buf_set_poll(struct udebug *ctx, struct udebug_remote_buf *rb, bool val);
178 void udebug_remote_buf_set_flags(struct udebug_remote_buf *rb, uint64_t mask, uint64_t set);
179 struct udebug_snapshot *udebug_remote_buf_snapshot(struct udebug_remote_buf *rb);
180 bool udebug_snapshot_get_entry(struct udebug_snapshot *s, struct udebug_iter *it, unsigned int entry);
181
182 void udebug_remote_buf_set_start_time(struct udebug_remote_buf *rb, uint64_t ts);
183 void udebug_remote_buf_set_start_offset(struct udebug_remote_buf *rb, uint32_t idx);
184
185 void udebug_iter_start(struct udebug_iter *it, struct udebug_snapshot **s, size_t n);
186 bool udebug_iter_next(struct udebug_iter *it);
187
188 void udebug_init(struct udebug *ctx);
189 int udebug_connect(struct udebug *ctx, const char *path);
190 void udebug_auto_connect(struct udebug *ctx, const char *path);
191 void udebug_add_uloop(struct udebug *ctx);
192 void udebug_poll(struct udebug *ctx);
193 void udebug_free(struct udebug *ctx);
194
195 static inline bool udebug_is_connected(struct udebug *ctx)
196 {
197 return ctx->fd.fd >= 0;
198 }
199
200 int udebug_id_cmp(const void *k1, const void *k2, void *ptr);
201
202 #endif