README.md: update CLI help
[project/udebug.git] / ring.c
1 #include "server.h"
2
3 static FILE *urandom;
4
5 AVL_TREE(rings, udebug_id_cmp, true, NULL);
6
7 struct client_ring *client_ring_get_by_id(struct client *cl, uint32_t id)
8 {
9 struct client_ring *r;
10
11 list_for_each_entry(r, &cl->bufs, list)
12 if (r->id == id)
13 return r;
14
15 return NULL;
16 }
17
18 static uint32_t gen_ring_id(void)
19 {
20 uint32_t val = 0;
21
22 if (!urandom && (urandom = fopen("/dev/urandom", "r")) == NULL)
23 return 0;
24
25 fread(&val, sizeof(val), 1, urandom);
26
27 return val;
28 }
29
30 struct client_ring *client_ring_alloc(struct client *cl)
31 {
32 enum {
33 RING_ATTR_NAME,
34 RING_ATTR_FLAGS,
35 __RING_ATTR_MAX,
36 };
37 static const struct blobmsg_policy policy[__RING_ATTR_MAX] = {
38 [RING_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
39 [RING_ATTR_FLAGS] = { "flags", BLOBMSG_TYPE_ARRAY },
40 };
41 struct udebug_client_msg *msg = &cl->rx_buf.msg;
42 struct blob_attr *tb[__RING_ATTR_MAX], *meta;
43 struct client_ring *r;
44 size_t meta_len;
45
46 if (cl->rx_fd < 0)
47 return NULL;
48
49 meta_len = blob_pad_len(&cl->rx_buf.data);
50 r = calloc_a(sizeof(*r), &meta, meta_len);
51 memcpy(meta, cl->rx_buf.buf, meta_len);
52
53 blobmsg_parse_attr(policy, __RING_ATTR_MAX, tb, meta);
54 if (!tb[RING_ATTR_NAME]) {
55 close(cl->rx_fd);
56 free(r);
57 return NULL;
58 }
59
60 r->name = blobmsg_get_string(tb[RING_ATTR_NAME]);
61 r->flags = tb[RING_ATTR_FLAGS];
62
63 r->cl = cl;
64 r->id = msg->id;
65 r->fd = cl->rx_fd;
66 r->ring_size = msg->ring_size;
67 r->data_size = msg->data_size;
68 list_add_tail(&r->list, &cl->bufs);
69
70 r->node.key = (void *)(uintptr_t)gen_ring_id();
71 avl_insert(&rings, &r->node);
72 udebug_ubus_ring_notify(r, true);
73 DC(2, cl, "add ring %d [%x] ring_size=%x data_size=%x", r->id, ring_id(r), r->ring_size, r->data_size);
74
75 return r;
76 }
77
78 void client_ring_free(struct client_ring *r)
79 {
80 DC(2, r->cl, "free ring %d [%x]", r->id, ring_id(r));
81 udebug_ubus_ring_notify(r, false);
82 avl_delete(&rings, &r->node);
83 list_del(&r->list);
84 close(r->fd);
85 free(r);
86 }