-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathring.c
91 lines (73 loc) · 1.97 KB
/
ring.c
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
#include "server.h"
static FILE *urandom;
AVL_TREE(rings, udebug_id_cmp, true, NULL);
struct client_ring *client_ring_get_by_id(struct client *cl, uint32_t id)
{
struct client_ring *r;
list_for_each_entry(r, &cl->bufs, list)
if (r->id == id)
return r;
return NULL;
}
static uint32_t gen_ring_id(void)
{
uint32_t val = 0;
if (!urandom && (urandom = fopen("/dev/urandom", "r")) == NULL)
return 0;
if (fread(&val, sizeof(val), 1, urandom) != 1)
return 0;
return val;
}
struct client_ring *client_ring_alloc(struct client *cl)
{
enum {
RING_ATTR_NAME,
RING_ATTR_FLAGS,
__RING_ATTR_MAX,
};
static const struct blobmsg_policy policy[__RING_ATTR_MAX] = {
[RING_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
[RING_ATTR_FLAGS] = { "flags", BLOBMSG_TYPE_ARRAY },
};
struct udebug_client_msg *msg = &cl->rx_buf.msg;
struct blob_attr *tb[__RING_ATTR_MAX], *meta;
struct client_ring *r;
size_t meta_len;
if (cl->rx_fd < 0) {
DC(2, cl, "missing file descriptor");
return NULL;
}
meta_len = blob_pad_len(&cl->rx_buf.data);
r = calloc_a(sizeof(*r), &meta, meta_len);
memcpy(meta, cl->rx_buf.buf, meta_len);
blobmsg_parse_attr(policy, __RING_ATTR_MAX, tb, meta);
if (!tb[RING_ATTR_NAME]) {
DC(2, cl, "missing ring name");
close(cl->rx_fd);
free(r);
return NULL;
}
r->name = blobmsg_get_string(tb[RING_ATTR_NAME]);
r->flags = tb[RING_ATTR_FLAGS];
r->cl = cl;
r->id = msg->id;
r->fd = cl->rx_fd;
cl->rx_fd = -1;
r->ring_size = msg->ring_size;
r->data_size = msg->data_size;
list_add_tail(&r->list, &cl->bufs);
r->node.key = (void *)(uintptr_t)gen_ring_id();
avl_insert(&rings, &r->node);
udebug_ubus_ring_notify(r, true);
DC(2, cl, "add ring %d [%x] ring_size=%x data_size=%x", r->id, ring_id(r), r->ring_size, r->data_size);
return r;
}
void client_ring_free(struct client_ring *r)
{
DC(2, r->cl, "free ring %d [%x]", r->id, ring_id(r));
udebug_ubus_ring_notify(r, false);
avl_delete(&rings, &r->node);
list_del(&r->list);
close(r->fd);
free(r);
}