unet-cli: strip initial newline in usage message
[project/unetd.git] / udht-ubus.c
1 #include <libubus.h>
2 #include "udht.h"
3 #include "curve25519.h"
4
5 static struct ubus_auto_conn conn;
6 static struct blob_buf b;
7
8 static void
9 udht_ubus_network_add(struct blob_attr *data, int seq)
10 {
11 static const struct blobmsg_policy net_policy =
12 { "config", BLOBMSG_TYPE_TABLE };
13 enum {
14 CONFIG_ATTR_AUTH_KEY,
15 CONFIG_ATTR_DHT,
16 __CONFIG_ATTR_MAX
17 };
18 static const struct blobmsg_policy policy[__CONFIG_ATTR_MAX] = {
19 [CONFIG_ATTR_AUTH_KEY] = { "auth_key", BLOBMSG_TYPE_STRING },
20 [CONFIG_ATTR_DHT] = { "dht", BLOBMSG_TYPE_BOOL },
21 };
22 struct blob_attr *tb[__CONFIG_ATTR_MAX];
23 struct blob_attr *config, *cur;
24 uint8_t auth_key[CURVE25519_KEY_SIZE];
25
26 blobmsg_parse(&net_policy, 1, &config, blobmsg_data(data), blobmsg_len(data));
27
28 if (!config)
29 return;
30
31 blobmsg_parse(policy, __CONFIG_ATTR_MAX, tb, blobmsg_data(config), blobmsg_len(config));
32 if ((cur = tb[CONFIG_ATTR_DHT]) == NULL || !blobmsg_get_u8(cur))
33 return;
34
35 if ((cur = tb[CONFIG_ATTR_AUTH_KEY]) == NULL ||
36 (b64_decode(blobmsg_get_string(cur), auth_key, CURVE25519_KEY_SIZE) !=
37 CURVE25519_KEY_SIZE))
38 return;
39
40 udht_network_add(auth_key, seq);
41 }
42
43
44 static void
45 udht_ubus_network_cb(struct ubus_request *req, int type,
46 struct blob_attr *msg)
47 {
48 static const struct blobmsg_policy policy =
49 { "networks", BLOBMSG_TYPE_TABLE };
50 struct blob_attr *networks, *cur;
51 int *seq = req->priv;
52 int rem;
53
54 blobmsg_parse(&policy, 1, &networks, blobmsg_data(msg), blobmsg_len(msg));
55
56 if (!networks)
57 return;
58
59 blobmsg_for_each_attr(cur, networks, rem)
60 udht_ubus_network_add(cur, *seq);
61 }
62
63 static void
64 udht_ubus_update_networks(struct ubus_context *ctx)
65 {
66 static int seq;
67 uint32_t id;
68
69 seq++;
70
71 if (ubus_lookup_id(ctx, "unetd", &id) == 0)
72 ubus_invoke(ctx, id, "network_get", b.head, udht_ubus_network_cb, &seq, 5000);
73
74 udht_network_flush(seq);
75 }
76
77 static int
78 udht_ubus_unetd_cb(struct ubus_context *ctx, struct ubus_object *obj,
79 struct ubus_request_data *req, const char *method,
80 struct blob_attr *msg)
81 {
82 udht_ubus_update_networks(ctx);
83
84 return 0;
85 }
86
87 static void
88 udht_subscribe_unetd(struct ubus_context *ctx)
89 {
90 static struct ubus_subscriber sub = {
91 .cb = udht_ubus_unetd_cb
92 };
93 uint32_t id;
94
95 if (!sub.obj.id && ubus_register_subscriber(ctx, &sub))
96 return;
97
98 if (ubus_lookup_id(ctx, "unetd", &id))
99 return;
100
101 ubus_subscribe(ctx, &sub, id);
102
103 /* ensure that unetd's socket is ready by testing if it's reachable over ubus */
104 if (ubus_invoke(ctx, id, "network_get", b.head, NULL, NULL, 10000))
105 return;
106
107 udht_reconnect();
108 udht_ubus_update_networks(ctx);
109 }
110
111 static void
112 udht_ubus_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
113 const char *type, struct blob_attr *msg)
114 {
115 static const struct blobmsg_policy policy =
116 { "path", BLOBMSG_TYPE_STRING };
117 struct blob_attr *attr;
118
119 blobmsg_parse(&policy, 1, &attr, blobmsg_data(msg), blobmsg_len(msg));
120 if (!attr)
121 return;
122
123 if (!strcmp(blobmsg_get_string(attr), "unetd"))
124 udht_subscribe_unetd(ctx);
125 }
126
127 static void
128 ubus_connect_handler(struct ubus_context *ctx)
129 {
130 static struct ubus_event_handler ev = {
131 .cb = udht_ubus_event_cb,
132 };
133
134 ubus_register_event_handler(ctx, &ev, "ubus.object.add");
135 udht_subscribe_unetd(ctx);
136 }
137
138 void udht_ubus_init(void)
139 {
140 blob_buf_init(&b, 0);
141 conn.cb = ubus_connect_handler;
142 ubus_auto_connect(&conn);
143 }