ubus: add notification for subscribers present/gone
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
This commit is contained in:
parent
d366a6de83
commit
a69f062cbd
9 changed files with 69 additions and 1 deletions
|
@ -18,7 +18,14 @@
|
||||||
static struct ubus_context *ctx;
|
static struct ubus_context *ctx;
|
||||||
static struct blob_buf b;
|
static struct blob_buf b;
|
||||||
|
|
||||||
static struct ubus_object test_client_object = {};
|
static void test_client_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Subscribers active: %d\n", obj->has_subscribers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ubus_object test_client_object = {
|
||||||
|
.subscribe_cb = test_client_subscribe_cb,
|
||||||
|
};
|
||||||
|
|
||||||
static void client_main(void)
|
static void client_main(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,5 +27,6 @@ void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
||||||
int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
|
int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
|
||||||
struct blob_attr *msg, int cmd, uint32_t peer);
|
struct blob_attr *msg, int cmd, uint32_t peer);
|
||||||
void ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
void ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
||||||
|
void ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -91,4 +91,22 @@ void __hidden ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msg
|
||||||
s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET]));
|
s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __hidden ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr)
|
||||||
|
{
|
||||||
|
struct blob_attr **attrbuf;
|
||||||
|
struct ubus_object *obj;
|
||||||
|
uint32_t objid;
|
||||||
|
|
||||||
|
attrbuf = ubus_parse_msg(hdr->data);
|
||||||
|
if (!attrbuf[UBUS_ATTR_OBJID] || !attrbuf[UBUS_ATTR_ACTIVE])
|
||||||
|
return;
|
||||||
|
|
||||||
|
objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
|
||||||
|
obj = avl_find_element(&ctx->objects, &objid, obj, avl);
|
||||||
|
if (!obj)
|
||||||
|
return;
|
||||||
|
|
||||||
|
obj->has_subscribers = blob_get_u8(attrbuf[UBUS_ATTR_ACTIVE]);
|
||||||
|
if (obj->subscribe_cb)
|
||||||
|
obj->subscribe_cb(ctx, obj);
|
||||||
|
}
|
||||||
|
|
|
@ -232,6 +232,10 @@ void __hidden ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr
|
||||||
case UBUS_MSG_UNSUBSCRIBE:
|
case UBUS_MSG_UNSUBSCRIBE:
|
||||||
ubus_process_unsubscribe(ctx, hdr);
|
ubus_process_unsubscribe(ctx, hdr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UBUS_MSG_NOTIFY:
|
||||||
|
ubus_process_notify(ctx, hdr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef void (*ubus_lookup_handler_t)(struct ubus_context *ctx,
|
||||||
typedef int (*ubus_handler_t)(struct ubus_context *ctx, struct ubus_object *obj,
|
typedef int (*ubus_handler_t)(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
struct ubus_request_data *req,
|
struct ubus_request_data *req,
|
||||||
const char *method, struct blob_attr *msg);
|
const char *method, struct blob_attr *msg);
|
||||||
|
typedef void (*ubus_state_handler_t)(struct ubus_context *ctx, struct ubus_object *obj);
|
||||||
typedef void (*ubus_remove_handler_t)(struct ubus_context *ctx,
|
typedef void (*ubus_remove_handler_t)(struct ubus_context *ctx,
|
||||||
struct ubus_subscriber *obj, uint32_t id);
|
struct ubus_subscriber *obj, uint32_t id);
|
||||||
typedef void (*ubus_event_handler_t)(struct ubus_context *ctx, struct ubus_event_handler *ev,
|
typedef void (*ubus_event_handler_t)(struct ubus_context *ctx, struct ubus_event_handler *ev,
|
||||||
|
@ -86,6 +87,9 @@ struct ubus_object {
|
||||||
const char *path;
|
const char *path;
|
||||||
struct ubus_object_type *type;
|
struct ubus_object_type *type;
|
||||||
|
|
||||||
|
ubus_state_handler_t subscribe_cb;
|
||||||
|
bool has_subscribers;
|
||||||
|
|
||||||
const struct ubus_method *methods;
|
const struct ubus_method *methods;
|
||||||
int n_methods;
|
int n_methods;
|
||||||
};
|
};
|
||||||
|
@ -134,6 +138,7 @@ struct ubus_request_data {
|
||||||
uint32_t peer;
|
uint32_t peer;
|
||||||
uint32_t seq;
|
uint32_t seq;
|
||||||
bool deferred;
|
bool deferred;
|
||||||
|
bool notify;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ubus_request {
|
struct ubus_request {
|
||||||
|
|
|
@ -167,6 +167,7 @@ free:
|
||||||
void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target, const char *method)
|
void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target, const char *method)
|
||||||
{
|
{
|
||||||
struct ubus_subscription *s;
|
struct ubus_subscription *s;
|
||||||
|
bool first = list_empty(&target->subscribers);
|
||||||
|
|
||||||
s = calloc(1, sizeof(*s) + strlen(method) + 1);
|
s = calloc(1, sizeof(*s) + strlen(method) + 1);
|
||||||
if (!s)
|
if (!s)
|
||||||
|
@ -177,13 +178,21 @@ void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target, const c
|
||||||
list_add(&s->list, &target->subscribers);
|
list_add(&s->list, &target->subscribers);
|
||||||
list_add(&s->target_list, &obj->target_list);
|
list_add(&s->target_list, &obj->target_list);
|
||||||
strcpy(s->method, method);
|
strcpy(s->method, method);
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
ubus_notify_subscription(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ubus_unsubscribe(struct ubus_subscription *s)
|
void ubus_unsubscribe(struct ubus_subscription *s)
|
||||||
{
|
{
|
||||||
|
struct ubus_object *obj = s->target;
|
||||||
|
|
||||||
list_del(&s->list);
|
list_del(&s->list);
|
||||||
list_del(&s->target_list);
|
list_del(&s->target_list);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
|
if (list_empty(&obj->subscribers))
|
||||||
|
ubus_notify_subscription(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ubusd_free_object(struct ubus_object *obj)
|
void ubusd_free_object(struct ubus_object *obj)
|
||||||
|
|
|
@ -79,5 +79,6 @@ static inline struct ubus_object *ubusd_find_object(uint32_t objid)
|
||||||
void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target, const char *method);
|
void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target, const char *method);
|
||||||
void ubus_unsubscribe(struct ubus_subscription *s);
|
void ubus_unsubscribe(struct ubus_subscription *s);
|
||||||
void ubus_notify_unsubscribe(struct ubus_subscription *s);
|
void ubus_notify_unsubscribe(struct ubus_subscription *s);
|
||||||
|
void ubus_notify_subscription(struct ubus_object *obj);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -416,6 +416,20 @@ void ubusd_proto_free_client(struct ubus_client *cl)
|
||||||
ubus_free_id(&clients, &cl->id);
|
ubus_free_id(&clients, &cl->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ubus_notify_subscription(struct ubus_object *obj)
|
||||||
|
{
|
||||||
|
bool active = !list_empty(&obj->subscribers);
|
||||||
|
struct ubus_msg_buf *ub;
|
||||||
|
|
||||||
|
blob_buf_init(&b, 0);
|
||||||
|
blob_put_int32(&b, UBUS_ATTR_OBJID, obj->id.id);
|
||||||
|
blob_put_int8(&b, UBUS_ATTR_ACTIVE, active);
|
||||||
|
|
||||||
|
ub = ubus_msg_from_blob(false);
|
||||||
|
ubus_msg_init(ub, UBUS_MSG_NOTIFY, ++obj->invoke_seq, 0);
|
||||||
|
ubus_msg_send(obj->client, ub, true);
|
||||||
|
}
|
||||||
|
|
||||||
void ubus_notify_unsubscribe(struct ubus_subscription *s)
|
void ubus_notify_unsubscribe(struct ubus_subscription *s)
|
||||||
{
|
{
|
||||||
struct ubus_msg_buf *ub;
|
struct ubus_msg_buf *ub;
|
||||||
|
|
|
@ -62,6 +62,13 @@ enum ubus_msg_type {
|
||||||
UBUS_MSG_SUBSCRIBE,
|
UBUS_MSG_SUBSCRIBE,
|
||||||
UBUS_MSG_UNSUBSCRIBE,
|
UBUS_MSG_UNSUBSCRIBE,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send a notification to all subscribers of an object.
|
||||||
|
* when sent from the server, it indicates a subscription
|
||||||
|
* status change
|
||||||
|
*/
|
||||||
|
UBUS_MSG_NOTIFY,
|
||||||
|
|
||||||
/* must be last */
|
/* must be last */
|
||||||
__UBUS_MSG_LAST,
|
__UBUS_MSG_LAST,
|
||||||
};
|
};
|
||||||
|
@ -81,6 +88,8 @@ enum ubus_msg_attr {
|
||||||
UBUS_ATTR_DATA,
|
UBUS_ATTR_DATA,
|
||||||
UBUS_ATTR_TARGET,
|
UBUS_ATTR_TARGET,
|
||||||
|
|
||||||
|
UBUS_ATTR_ACTIVE,
|
||||||
|
|
||||||
/* must be last */
|
/* must be last */
|
||||||
UBUS_ATTR_MAX,
|
UBUS_ATTR_MAX,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue