1 /* 2 * Copyright (C) 2011-2014 Felix Fietkau <nbd@openwrt.org> 3 * 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 7 * 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. 12 */ 13 14 #ifndef __LIBUBUS_H 15 #define __LIBUBUS_H 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 #include <libubox/avl.h> 22 #include <libubox/list.h> 23 #include <libubox/blobmsg.h> 24 #include <libubox/uloop.h> 25 #include <stdint.h> 26 #include "ubusmsg.h" 27 #include "ubus_common.h" 28 29 #define UBUS_MAX_NOTIFY_PEERS 16 30 31 struct ubus_context; 32 struct ubus_msg_src; 33 struct ubus_object; 34 struct ubus_request; 35 struct ubus_request_data; 36 struct ubus_object_data; 37 struct ubus_event_handler; 38 struct ubus_subscriber; 39 struct ubus_notify_request; 40 41 struct ubus_msghdr_buf { 42 struct ubus_msghdr hdr; 43 struct blob_attr *data; 44 }; 45 46 typedef void (*ubus_lookup_handler_t)(struct ubus_context *ctx, 47 struct ubus_object_data *obj, 48 void *priv); 49 typedef int (*ubus_handler_t)(struct ubus_context *ctx, struct ubus_object *obj, 50 struct ubus_request_data *req, 51 const char *method, struct blob_attr *msg); 52 typedef void (*ubus_state_handler_t)(struct ubus_context *ctx, struct ubus_object *obj); 53 typedef void (*ubus_remove_handler_t)(struct ubus_context *ctx, 54 struct ubus_subscriber *obj, uint32_t id); 55 typedef void (*ubus_event_handler_t)(struct ubus_context *ctx, struct ubus_event_handler *ev, 56 const char *type, struct blob_attr *msg); 57 typedef void (*ubus_data_handler_t)(struct ubus_request *req, 58 int type, struct blob_attr *msg); 59 typedef void (*ubus_fd_handler_t)(struct ubus_request *req, int fd); 60 typedef void (*ubus_complete_handler_t)(struct ubus_request *req, int ret); 61 typedef void (*ubus_notify_complete_handler_t)(struct ubus_notify_request *req, 62 int idx, int ret); 63 typedef void (*ubus_notify_data_handler_t)(struct ubus_notify_request *req, 64 int type, struct blob_attr *msg); 65 typedef void (*ubus_connect_handler_t)(struct ubus_context *ctx); 66 typedef bool (*ubus_new_object_handler_t)(struct ubus_context *ctx, struct ubus_subscriber *sub, const char *path); 67 68 #define UBUS_OBJECT_TYPE(_name, _methods) \ 69 { \ 70 .name = _name, \ 71 .id = 0, \ 72 .methods = _methods, \ 73 .n_methods = ARRAY_SIZE(_methods) \ 74 } 75 76 #define __UBUS_METHOD_BASE(_name, _handler, _mask, _tags) \ 77 .name = _name, \ 78 .handler = _handler, \ 79 .mask = _mask, \ 80 .tags = _tags 81 82 #define __UBUS_METHOD_NOARG(_name, _handler, _mask, _tags) \ 83 __UBUS_METHOD_BASE(_name, _handler, _mask, _tags), \ 84 .policy = NULL, \ 85 .n_policy = 0 86 87 #define __UBUS_METHOD(_name, _handler, _mask, _policy, _tags) \ 88 __UBUS_METHOD_BASE(_name, _handler, _mask, _tags), \ 89 .policy = _policy, \ 90 .n_policy = ARRAY_SIZE(_policy) 91 92 #define UBUS_METHOD(_name, _handler, _policy) \ 93 { __UBUS_METHOD(_name, _handler, 0, _policy, 0) } 94 95 #define UBUS_METHOD_TAG(_name, _handler, _policy, _tags)\ 96 { __UBUS_METHOD(_name, _handler, 0, _policy, _tags) } 97 98 #define UBUS_METHOD_MASK(_name, _handler, _policy, _mask) \ 99 { __UBUS_METHOD(_name, _handler, _mask, _policy, 0) } 100 101 #define UBUS_METHOD_NOARG(_name, _handler) \ 102 { __UBUS_METHOD_NOARG(_name, _handler, 0, 0) } 103 104 #define UBUS_METHOD_TAG_NOARG(_name, _handler, _tags) \ 105 { __UBUS_METHOD_NOARG(_name, _handler, 0, _tags) } 106 107 #define UBUS_TAG_STATUS (1ul << 0) 108 #define UBUS_TAG_ADMIN (1ul << 1) 109 #define UBUS_TAG_PRIVATE (1ul << 2) 110 111 struct ubus_method { 112 const char *name; 113 ubus_handler_t handler; 114 115 unsigned long mask; 116 unsigned long tags; 117 const struct blobmsg_policy *policy; 118 int n_policy; 119 }; 120 121 struct ubus_object_type { 122 const char *name; 123 uint32_t id; 124 125 const struct ubus_method *methods; 126 int n_methods; 127 }; 128 129 struct ubus_object { 130 struct avl_node avl; 131 132 const char *name; 133 uint32_t id; 134 135 const char *path; 136 struct ubus_object_type *type; 137 138 ubus_state_handler_t subscribe_cb; 139 bool has_subscribers; 140 141 const struct ubus_method *methods; 142 int n_methods; 143 }; 144 145 struct ubus_subscriber { 146 struct list_head list; 147 struct ubus_object obj; 148 149 ubus_handler_t cb; 150 ubus_remove_handler_t remove_cb; 151 ubus_new_object_handler_t new_obj_cb; 152 }; 153 154 struct ubus_event_handler { 155 struct ubus_object obj; 156 157 ubus_event_handler_t cb; 158 }; 159 160 struct ubus_context { 161 struct list_head requests; 162 struct avl_tree objects; 163 struct list_head pending; 164 165 struct uloop_fd sock; 166 struct uloop_timeout pending_timer; 167 168 uint32_t local_id; 169 uint16_t request_seq; 170 bool cancel_poll; 171 int stack_depth; 172 173 void (*connection_lost)(struct ubus_context *ctx); 174 void (*monitor_cb)(struct ubus_context *ctx, uint32_t seq, struct blob_attr *data); 175 176 struct ubus_msghdr_buf msgbuf; 177 uint32_t msgbuf_data_len; 178 int msgbuf_reduction_counter; 179 180 union { 181 struct { 182 struct list_head auto_subscribers; 183 struct ubus_event_handler auto_subscribe_event_handler; 184 }; 185 struct { 186 ubus_handler_t request_handler; 187 }; 188 }; 189 }; 190 191 struct ubus_object_data { 192 uint32_t id; 193 uint32_t type_id; 194 const char *path; 195 struct blob_attr *signature; 196 }; 197 198 struct ubus_acl_key { 199 const char *user; 200 const char *group; 201 const char *object; 202 }; 203 204 struct ubus_request_data { 205 uint32_t object; 206 uint32_t peer; 207 uint16_t seq; 208 209 struct ubus_acl_key acl; 210 211 /* internal use */ 212 bool deferred; 213 int fd; 214 int req_fd; /* fd received from the initial request */ 215 }; 216 217 struct ubus_request { 218 struct list_head list; 219 220 struct list_head pending; 221 int status_code; 222 bool status_msg; 223 bool blocked; 224 bool cancelled; 225 bool notify; 226 227 uint32_t peer; 228 uint16_t seq; 229 230 ubus_data_handler_t raw_data_cb; 231 ubus_data_handler_t data_cb; 232 ubus_fd_handler_t fd_cb; 233 ubus_complete_handler_t complete_cb; 234 235 int fd; 236 237 struct ubus_context *ctx; 238 void *priv; 239 }; 240 241 struct ubus_notify_request { 242 struct ubus_request req; 243 244 ubus_notify_complete_handler_t status_cb; 245 ubus_notify_complete_handler_t complete_cb; 246 ubus_notify_data_handler_t data_cb; 247 248 uint32_t pending; 249 uint32_t id[UBUS_MAX_NOTIFY_PEERS + 1]; 250 }; 251 252 struct ubus_auto_conn { 253 struct ubus_context ctx; 254 struct uloop_timeout timer; 255 const char *path; 256 ubus_connect_handler_t cb; 257 }; 258 259 struct ubus_context *ubus_connect(const char *path); 260 int ubus_connect_ctx(struct ubus_context *ctx, const char *path); 261 void ubus_auto_connect(struct ubus_auto_conn *conn); 262 int ubus_reconnect(struct ubus_context *ctx, const char *path); 263 int ubus_channel_connect(struct ubus_context *ctx, int fd, 264 ubus_handler_t handler); 265 int ubus_channel_create(struct ubus_context *ctx, int *remote_fd, 266 ubus_handler_t handler); 267 void ubus_flush_requests(struct ubus_context *ctx); 268 269 static inline bool 270 ubus_context_is_channel(struct ubus_context *ctx) 271 { 272 return ctx->local_id == UBUS_CLIENT_ID_CHANNEL; 273 } 274 275 /* call this only for struct ubus_context pointers returned by ubus_connect() */ 276 void ubus_free(struct ubus_context *ctx); 277 278 /* call this only for struct ubus_context pointers initialised by ubus_connect_ctx() */ 279 void ubus_shutdown(struct ubus_context *ctx); 280 281 static inline void ubus_auto_shutdown(struct ubus_auto_conn *conn) 282 { 283 uloop_timeout_cancel(&conn->timer); 284 ubus_shutdown(&conn->ctx); 285 } 286 287 const char *ubus_strerror(int error); 288 289 static inline void ubus_add_uloop(struct ubus_context *ctx) 290 { 291 uloop_fd_add(&ctx->sock, ULOOP_BLOCKING | ULOOP_READ); 292 } 293 294 /* call this for read events on ctx->sock.fd when not using uloop */ 295 static inline void ubus_handle_event(struct ubus_context *ctx) 296 { 297 ctx->sock.cb(&ctx->sock, ULOOP_READ); 298 } 299 300 /* ----------- raw request handling ----------- */ 301 302 /* wait for a request to complete and return its status */ 303 int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req, 304 int timeout); 305 306 /* complete a request asynchronously */ 307 void ubus_complete_request_async(struct ubus_context *ctx, 308 struct ubus_request *req); 309 310 /* abort an asynchronous request */ 311 void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req); 312 313 /* ----------- objects ----------- */ 314 315 int ubus_lookup(struct ubus_context *ctx, const char *path, 316 ubus_lookup_handler_t cb, void *priv); 317 318 int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id); 319 320 /* make an object visible to remote connections */ 321 int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj); 322 323 /* remove the object from the ubus connection */ 324 int ubus_remove_object(struct ubus_context *ctx, struct ubus_object *obj); 325 326 /* add a subscriber notifications from another object */ 327 int ubus_register_subscriber(struct ubus_context *ctx, struct ubus_subscriber *obj); 328 329 static inline int 330 ubus_unregister_subscriber(struct ubus_context *ctx, struct ubus_subscriber *obj) 331 { 332 if (!list_empty(&obj->list)) 333 list_del_init(&obj->list); 334 return ubus_remove_object(ctx, &obj->obj); 335 } 336 337 int ubus_subscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id); 338 int ubus_unsubscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id); 339 340 int __ubus_monitor(struct ubus_context *ctx, const char *type); 341 342 static inline int ubus_monitor_start(struct ubus_context *ctx) 343 { 344 return __ubus_monitor(ctx, "add"); 345 } 346 347 static inline int ubus_monitor_stop(struct ubus_context *ctx) 348 { 349 return __ubus_monitor(ctx, "remove"); 350 } 351 352 353 /* ----------- acl ----------- */ 354 355 struct acl_object { 356 struct ubus_acl_key key; 357 struct avl_node avl; 358 struct blob_attr *acl; 359 }; 360 361 extern struct avl_tree acl_objects; 362 int ubus_register_acl(struct ubus_context *ctx); 363 364 #define acl_for_each(o, m) \ 365 if ((m)->object && (m)->user && (m)->group) \ 366 avl_for_element_range(avl_find_ge_element(&acl_objects, m, o, avl), avl_find_le_element(&acl_objects, m, o, avl), o, avl) 367 368 /* ----------- rpc ----------- */ 369 370 /* invoke a method on a specific object */ 371 int ubus_invoke_fd(struct ubus_context *ctx, uint32_t obj, const char *method, 372 struct blob_attr *msg, ubus_data_handler_t cb, void *priv, 373 int timeout, int fd); 374 static inline int 375 ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method, 376 struct blob_attr *msg, ubus_data_handler_t cb, void *priv, 377 int timeout) 378 { 379 return ubus_invoke_fd(ctx, obj, method, msg, cb, priv, timeout, -1); 380 } 381 382 /* asynchronous version of ubus_invoke() */ 383 int ubus_invoke_async_fd(struct ubus_context *ctx, uint32_t obj, const char *method, 384 struct blob_attr *msg, struct ubus_request *req, int fd); 385 static inline int 386 ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method, 387 struct blob_attr *msg, struct ubus_request *req) 388 { 389 return ubus_invoke_async_fd(ctx, obj, method, msg, req, -1); 390 } 391 392 /* send a reply to an incoming object method call */ 393 int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req, 394 struct blob_attr *msg); 395 396 static inline void ubus_defer_request(struct ubus_context *ctx, 397 struct ubus_request_data *req, 398 struct ubus_request_data *new_req) 399 { 400 (void) ctx; 401 memcpy(new_req, req, sizeof(*req)); 402 req->deferred = true; 403 } 404 405 static inline void ubus_request_set_fd(struct ubus_context *ctx, 406 struct ubus_request_data *req, int fd) 407 { 408 (void) ctx; 409 req->fd = fd; 410 } 411 412 static inline int ubus_request_get_caller_fd(struct ubus_request_data *req) 413 { 414 int fd = req->req_fd; 415 req->req_fd = -1; 416 417 return fd; 418 } 419 420 void ubus_complete_deferred_request(struct ubus_context *ctx, 421 struct ubus_request_data *req, int ret); 422 423 /* 424 * send a notification to all subscribers of an object 425 * if timeout < 0, no reply is expected from subscribers 426 */ 427 int ubus_notify(struct ubus_context *ctx, struct ubus_object *obj, 428 const char *type, struct blob_attr *msg, int timeout); 429 430 int ubus_notify_async(struct ubus_context *ctx, struct ubus_object *obj, 431 const char *type, struct blob_attr *msg, 432 struct ubus_notify_request *req); 433 434 435 /* ----------- events ----------- */ 436 437 int ubus_send_event(struct ubus_context *ctx, const char *id, 438 struct blob_attr *data); 439 440 int ubus_register_event_handler(struct ubus_context *ctx, 441 struct ubus_event_handler *ev, 442 const char *pattern); 443 444 static inline int ubus_unregister_event_handler(struct ubus_context *ctx, 445 struct ubus_event_handler *ev) 446 { 447 return ubus_remove_object(ctx, &ev->obj); 448 } 449 450 #ifdef __cplusplus 451 } 452 #endif 453 454 #endif 455
This page was automatically generated by LXR 0.3.1. • OpenWrt