lib: fix dealing with udebugd restarts
[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 if (fread(&val, sizeof(val), 1, urandom) != 1)
26 return 0;
27
28 return val;
29 }
30
31 struct client_ring *client_ring_alloc(struct client *cl)
32 {
33 enum {
34 RING_ATTR_NAME,
35 RING_ATTR_FLAGS,
36 __RING_ATTR_MAX,
37 };
38 static const struct blobmsg_policy policy[__RING_ATTR_MAX] = {
39 [RING_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
40 [RING_ATTR_FLAGS] = { "flags", BLOBMSG_TYPE_ARRAY },
41 };
42 struct udebug_client_msg *msg = &cl->rx_buf.msg;
43 struct blob_attr *tb[__RING_ATTR_MAX], *meta;
44 struct client_ring *r;
45 size_t meta_len;
46
47 if (cl->rx_fd < 0)
48 return NULL;
49
50 meta_len = blob_pad_len(&cl->rx_buf.data);
51 r = calloc_a(sizeof(*r), &meta, meta_len);
52 memcpy(meta, cl->rx_buf.buf, meta_len);
53
54 blobmsg_parse_attr(policy, __RING_ATTR_MAX, tb, meta);
55 if (!tb[RING_ATTR_NAME]) {
56 close(cl->rx_fd);
57 free(r);
58 return NULL;
59 }
60
61 r->name = blobmsg_get_string(tb[RING_ATTR_NAME]);
62 r->flags = tb[RING_ATTR_FLAGS];
63
64 r->cl = cl;
65 r->id = msg->id;
66 r->fd = cl->rx_fd;
67 cl->rx_fd = -1;
68 r->ring_size = msg->ring_size;
69 r->data_size = msg->data_size;
70 list_add_tail(&r->list, &cl->bufs);
71
72 r->node.key = (void *)(uintptr_t)gen_ring_id();
73 avl_insert(&rings, &r->node);
74 udebug_ubus_ring_notify(r, true);
75 DC(2, cl, "add ring %d [%x] ring_size=%x data_size=%x", r->id, ring_id(r), r->ring_size, r->data_size);
76
77 return r;
78 }
79
80 void client_ring_free(struct client_ring *r)
81 {
82 DC(2, r->cl, "free ring %d [%x]", r->id, ring_id(r));
83 udebug_ubus_ring_notify(r, false);
84 avl_delete(&rings, &r->node);
85 list_del(&r->list);
86 close(r->fd);
87 free(r);
88 }