2 * Copyright (C) 2011-2012 Felix Fietkau <nbd@openwrt.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include "libubus-internal.h"
17 static int ubus_subscriber_cb(struct ubus_context
*ctx
, struct ubus_object
*obj
,
18 struct ubus_request_data
*req
,
19 const char *method
, struct blob_attr
*msg
)
21 struct ubus_subscriber
*s
;
23 s
= container_of(obj
, struct ubus_subscriber
, obj
);
25 return s
->cb(ctx
, obj
, req
, method
, msg
);
29 const struct ubus_method watch_method __hidden
= {
31 .handler
= ubus_subscriber_cb
,
35 ubus_auto_sub_event_handler_cb(struct ubus_context
*ctx
, struct ubus_event_handler
*ev
,
36 const char *type
, struct blob_attr
*msg
)
44 static const struct blobmsg_policy event_policy
[__EVENT_MAX
] = {
45 [EVENT_ID
] = { .name
= "id", .type
= BLOBMSG_TYPE_INT32
},
46 [EVENT_PATH
] = { .name
= "path", .type
= BLOBMSG_TYPE_STRING
},
49 struct blob_attr
*tb
[__EVENT_MAX
];
50 struct ubus_subscriber
*s
;
54 blobmsg_parse(event_policy
, __EVENT_MAX
, tb
, blob_data(msg
), blob_len(msg
));
56 if (!tb
[EVENT_ID
] || !tb
[EVENT_PATH
])
59 path
= blobmsg_get_string(tb
[EVENT_PATH
]);
60 id
= blobmsg_get_u32(tb
[EVENT_ID
]);
62 list_for_each_entry(s
, &ctx
->auto_subscribers
, list
)
63 if (s
->new_obj_cb(ctx
, s
, path
))
64 ubus_subscribe(ctx
, s
, id
);
68 ubus_auto_sub_lookup(struct ubus_context
*ctx
, struct ubus_object_data
*obj
,
71 struct ubus_subscriber
*s
= priv
;
73 if (s
->new_obj_cb(ctx
, s
, obj
->path
))
74 ubus_subscribe(ctx
, s
, obj
->id
);
77 int ubus_register_subscriber(struct ubus_context
*ctx
, struct ubus_subscriber
*s
)
79 struct ubus_object
*obj
= &s
->obj
;
82 INIT_LIST_HEAD(&s
->list
);
83 obj
->methods
= &watch_method
;
86 ret
= ubus_add_object(ctx
, obj
);
91 struct ubus_event_handler
*ev
= &ctx
->auto_subscribe_event_handler
;
92 list_add(&s
->list
, &ctx
->auto_subscribers
);
93 ev
->cb
= ubus_auto_sub_event_handler_cb
;
95 ubus_register_event_handler(ctx
, ev
, "ubus.object.add");
96 ubus_lookup(ctx
, NULL
, ubus_auto_sub_lookup
, s
);
103 __ubus_subscribe_request(struct ubus_context
*ctx
, struct ubus_object
*obj
, uint32_t id
, int type
)
105 struct ubus_request req
;
107 blob_buf_init(&b
, 0);
108 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
);
109 blob_put_int32(&b
, UBUS_ATTR_TARGET
, id
);
111 if (ubus_start_request(ctx
, &req
, b
.head
, type
, 0) < 0)
112 return UBUS_STATUS_INVALID_ARGUMENT
;
114 return ubus_complete_request(ctx
, &req
, 0);
118 int ubus_subscribe(struct ubus_context
*ctx
, struct ubus_subscriber
*obj
, uint32_t id
)
120 return __ubus_subscribe_request(ctx
, &obj
->obj
, id
, UBUS_MSG_SUBSCRIBE
);
123 int ubus_unsubscribe(struct ubus_context
*ctx
, struct ubus_subscriber
*obj
, uint32_t id
)
125 return __ubus_subscribe_request(ctx
, &obj
->obj
, id
, UBUS_MSG_UNSUBSCRIBE
);