X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=lib.c;h=55a272ae0efbc3cbb98381cfc1bb207430ad61e1;hb=HEAD;hp=caba7d9a1f9f25ab0c7b36a45c3e8539fe02b4f0;hpb=a92101631c0dd2c466dfe22ffd752b36929b2f69;p=project%2Fudebug.git diff --git a/lib.c b/lib.c index caba7d9..55a272a 100644 --- a/lib.c +++ b/lib.c @@ -1,742 +1,194 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "priv.h" - -#include - -#define ALIGN(i, sz) (((i) + (sz) - 1) & ~((sz) - 1)) - -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif - -#define UDEBUG_MIN_ALLOC_LEN 128 -static struct blob_buf b; - -static void __randname(char *template) -{ - int i; - struct timespec ts; - unsigned long r; - - clock_gettime(CLOCK_REALTIME, &ts); - r = ts.tv_sec + ts.tv_nsec; - for (i=0; i<6; i++, r>>=5) - template[i] = 'A'+(r&15)+(r&16)*2; -} - -int udebug_id_cmp(const void *k1, const void *k2, void *ptr) -{ - uint32_t id1 = (uint32_t)(uintptr_t)k1, id2 = (uint32_t)(uintptr_t)k2; - if (id1 < id2) - return -1; - else if (id1 > id2) - return 1; - return 0; -} - -static inline int -shm_open_anon(char *name) -{ - char *template = name + strlen(name) - 6; - int fd; - - if (template < name || memcmp(template, "XXXXXX", 6) != 0) - return -1; - - for (int i = 0; i < 100; i++) { - __randname(template); - fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd >= 0) { - if (shm_unlink(name) < 0) { - close(fd); - continue; - } - return fd; - } - - if (fd < 0 && errno != EEXIST) - return -1; - } - - return -1; -} - -uint64_t udebug_timestamp(void) -{ - struct timespec ts; - uint64_t val; - - clock_gettime(CLOCK_REALTIME, &ts); - - val = ts.tv_sec; - val *= UDEBUG_TS_SEC; - val += ts.tv_nsec / 1000; - - return val; -} - -static int -__udebug_buf_map(struct udebug_buf *buf) -{ - void *ptr, *ptr2; - - ptr = mmap(NULL, buf->head_size + 2 * buf->data_size, PROT_NONE, - MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - if (ptr == MAP_FAILED) - return -1; - - ptr2 = mmap(ptr, buf->head_size + buf->data_size, - PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, buf->fd, 0); - if (ptr2 != ptr) - goto err_unmap; - - ptr2 = mmap(ptr + buf->head_size + buf->data_size, buf->data_size, - PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, buf->fd, - buf->head_size); - if (ptr2 != ptr + buf->head_size + buf->data_size) - goto err_unmap; - - buf->hdr = ptr; - buf->data = ptr + buf->head_size; - return 0; - -err_unmap: - munmap(ptr, buf->head_size + 2 * buf->data_size); - return -1; -} - -static int -writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd) -{ - uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 }; - struct msghdr msghdr = { 0 }; - struct cmsghdr *cmsg; - int len = 0; - int *pfd; - - msghdr.msg_iov = iov, - msghdr.msg_iovlen = iov_len, - msghdr.msg_control = fd_buf; - msghdr.msg_controllen = sizeof(fd_buf); - - cmsg = CMSG_FIRSTHDR(&msghdr); - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - - pfd = (int *) CMSG_DATA(cmsg); - msghdr.msg_controllen = cmsg->cmsg_len; - - do { - ssize_t cur_len; - - if (sock_fd < 0) { - msghdr.msg_control = NULL; - msghdr.msg_controllen = 0; - } else { - *pfd = sock_fd; - } - - cur_len = sendmsg(fd, &msghdr, 0); - if (cur_len < 0) { - struct pollfd pfd = { - .fd = fd, - .events = POLLOUT - }; - - switch(errno) { - case EAGAIN: - poll(&pfd, 1, -1); - break; - case EINTR: - break; - default: - return -1; - } - continue; - } - - if (len > 0) - sock_fd = -1; - - len += cur_len; - while (cur_len >= (ssize_t) iov->iov_len) { - cur_len -= iov->iov_len; - iov_len--; - iov++; - if (!iov_len) - return len; - } - iov->iov_base += cur_len; - iov->iov_len -= cur_len; - msghdr.msg_iov = iov; - msghdr.msg_iovlen = iov_len; - } while (1); - - /* Should never reach here */ - return -1; -} - -static int -recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd) -{ - uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 }; - struct msghdr msghdr = { 0 }; - struct cmsghdr *cmsg; - int total = 0; - int bytes; - int *pfd; - - msghdr.msg_iov = iov, - msghdr.msg_iovlen = 1, - msghdr.msg_control = fd_buf; - msghdr.msg_controllen = sizeof(fd_buf); - - cmsg = CMSG_FIRSTHDR(&msghdr); - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - - pfd = (int *) CMSG_DATA(cmsg); - - while (iov->iov_len > 0) { - if (recv_fd) { - msghdr.msg_control = fd_buf; - msghdr.msg_controllen = cmsg->cmsg_len; - } else { - msghdr.msg_control = NULL; - msghdr.msg_controllen = 0; - } - - *pfd = -1; - bytes = recvmsg(fd, &msghdr, 0); - if (!bytes) - return -2; - if (bytes < 0) { - bytes = 0; - if (errno == EINTR) - continue; - - if (errno != EAGAIN) - return -2; - } - if (!wait && !bytes) - return 0; - - if (recv_fd) - *recv_fd = *pfd; - else if (*pfd >= 0) - close(*pfd); - - if (bytes > 0) - recv_fd = NULL; - - wait = true; - iov->iov_len -= bytes; - iov->iov_base += bytes; - total += bytes; - - if (iov->iov_len > 0) { - struct pollfd pfd = { - .fd = fd, - .events = POLLIN - }; - int ret; - do { - ret = poll(&pfd, 1, UDEBUG_TIMEOUT); - } while (ret < 0 && errno == EINTR); - - if (!(pfd.revents & POLLIN)) - return -1; - } - } - - return total; -} - -void udebug_send_msg(struct udebug *ctx, struct udebug_client_msg *msg, - struct blob_attr *meta, int fd) -{ - struct iovec iov[2] = { - { .iov_base = msg, .iov_len = sizeof(*msg) }, - {} - }; - - if (!meta) { - blob_buf_init(&b, 0); - meta = b.head; - } - - iov[1].iov_base = meta; - iov[1].iov_len = blob_pad_len(meta); - writev_retry(ctx->fd.fd, iov, ARRAY_SIZE(iov), fd); -} - -static void -udebug_buf_msg(struct udebug_buf *buf, enum udebug_client_msg_type type) -{ - struct udebug_client_msg msg = { - .type = type, - .id = buf->id, - }; - - udebug_send_msg(buf->ctx, &msg, NULL, -1); -} - -static size_t __udebug_headsize(unsigned int ring_size, unsigned int page_size) -{ - ring_size *= sizeof(struct udebug_ptr); - return ALIGN(sizeof(struct udebug_hdr) + ring_size, page_size); -} - -int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t data_size) -{ - INIT_LIST_HEAD(&buf->list); - buf->fd = fd; - buf->ring_size = ring_size; - buf->head_size = __udebug_headsize(ring_size, sysconf(_SC_PAGESIZE)); - buf->data_size = data_size; - - if (buf->ring_size > (1U << 24) || buf->data_size > (1U << 29)) - return -1; - - if (__udebug_buf_map(buf)) - return -1; - - if (buf->ring_size != buf->hdr->ring_size || - buf->data_size != buf->hdr->data_size) { - munmap(buf->hdr, buf->head_size + 2 * buf->data_size); - buf->hdr = NULL; - return -1; - } - - return 0; -} - -int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size) -{ - uint32_t pagesz = sysconf(_SC_PAGESIZE); - char filename[] = "/udebug.XXXXXX"; - unsigned int order = 12; - uint8_t ring_order = 5; - size_t head_size; - int fd; - - INIT_LIST_HEAD(&buf->list); - if (size < pagesz) - size = pagesz; - while(size > 1 << order) - order++; - size = 1 << order; - while (entries > 1 << ring_order) - ring_order++; - entries = 1 << ring_order; - - if (size > (1U << 29) || entries > (1U << 24)) - return -1; - - head_size = __udebug_headsize(entries, pagesz); - while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), pagesz) == head_size) - entries *= 2; - - fd = shm_open_anon(filename); - if (fd < 0) - return -1; - - if (ftruncate(fd, head_size + size) < 0) - goto err_close; - - buf->head_size = head_size; - buf->data_size = size; - buf->ring_size = entries; - buf->fd = fd; - - if (__udebug_buf_map(buf)) - goto err_close; - - buf->hdr->ring_size = entries; - buf->hdr->data_size = size; - - /* ensure hdr changes are visible */ - __sync_synchronize(); - - return 0; - -err_close: - close(fd); - return -1; -} - -static void *udebug_buf_alloc(struct udebug_buf *buf, uint32_t ofs, uint32_t len) -{ - struct udebug_hdr *hdr = buf->hdr; - - hdr->data_used = u32_max(hdr->data_used, ofs + len + 1); - - /* ensure that data_used update is visible before clobbering data */ - __sync_synchronize(); - - return udebug_buf_ptr(buf, ofs); -} - -uint64_t udebug_buf_flags(struct udebug_buf *buf) -{ - struct udebug_hdr *hdr = buf->hdr; - uint64_t flags; - - if (!hdr) - return 0; - - flags = hdr->flags[0]; - if (sizeof(flags) != sizeof(uintptr_t)) - flags |= ((uint64_t)hdr->flags[1]) << 32; - - return flags; -} +#include "udebug.h" -void udebug_entry_init_ts(struct udebug_buf *buf, uint64_t timestamp) +static struct blob_attr * +find_attr(struct blob_attr *attr, const char *name, enum blobmsg_type type) { - struct udebug_hdr *hdr = buf->hdr; - struct udebug_ptr *ptr; + struct blobmsg_policy policy = { name, type }; + struct blob_attr *ret; - if (!hdr) - return; - - ptr = udebug_ring_ptr(hdr, hdr->head); - ptr->start = hdr->data_head; - ptr->len = 0; - ptr->timestamp = timestamp; -} - -void *udebug_entry_append(struct udebug_buf *buf, const void *data, uint32_t len) -{ - struct udebug_hdr *hdr = buf->hdr; - struct udebug_ptr *ptr; - uint32_t ofs; - void *ret; - - if (!hdr) - return NULL; - - ptr = udebug_ring_ptr(hdr, hdr->head); - ofs = ptr->start + ptr->len; - if (ptr->len + len > buf->data_size / 2) + if (!attr) return NULL; - ret = udebug_buf_alloc(buf, ofs, len); - if (data) - memcpy(ret, data, len); - ptr->len += len; - + blobmsg_parse_attr(&policy, 1, &ret, attr); return ret; } -int udebug_entry_printf(struct udebug_buf *buf, const char *fmt, ...) +static void +udebug_ubus_msg_cb(struct udebug_ubus *ctx, struct blob_attr *data) { - va_list ap; - size_t ret; + struct blob_attr *en_attr; + bool enabled; - va_start(ap, fmt); - ret = udebug_entry_vprintf(buf, fmt, ap); - va_end(ap); + data = find_attr(data, "service", BLOBMSG_TYPE_TABLE); + data = find_attr(data, ctx->service, BLOBMSG_TYPE_TABLE); + if (!data) + return; - return ret; + en_attr = find_attr(data, "enabled", BLOBMSG_TYPE_STRING); + enabled = en_attr && !!atoi(blobmsg_get_string(en_attr)); + ctx->cb(ctx, data, enabled); } -int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap) +static int +udebug_ubus_notify_cb(struct ubus_context *ubus, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) { - struct udebug_hdr *hdr = buf->hdr; - struct udebug_ptr *ptr; - uint32_t ofs; - uint32_t len; - char *str; - - if (!hdr) - return -1; - - ptr = udebug_ring_ptr(hdr, hdr->head); - ofs = ptr->start + ptr->len; - if (ptr->len > buf->data_size / 2) - return -1; + struct udebug_ubus *ctx = container_of(obj, struct udebug_ubus, sub.obj); - str = udebug_buf_alloc(buf, ofs, UDEBUG_MIN_ALLOC_LEN); - len = vsnprintf(str, UDEBUG_MIN_ALLOC_LEN, fmt, ap); - if (len <= UDEBUG_MIN_ALLOC_LEN) - goto out; + if (!strcmp(method, "config")) + udebug_ubus_msg_cb(ctx, msg); - if (ptr->len + len > buf->data_size / 2) - return -1; - - udebug_buf_alloc(buf, ofs, len + 1); - len = vsnprintf(str, len, fmt, ap); - -out: - ptr->len += len; return 0; } -void udebug_entry_add(struct udebug_buf *buf) -{ - struct udebug_hdr *hdr = buf->hdr; - struct udebug_ptr *ptr = udebug_ring_ptr(hdr, hdr->head); - uint32_t notify; - uint8_t *data; - - /* ensure strings are always 0-terminated */ - data = udebug_buf_ptr(buf, ptr->start + ptr->len); - *data = 0; - hdr->data_head = ptr->start + ptr->len + 1; - - /* ensure that all data changes are visible before advancing head */ - __sync_synchronize(); - - u32_set(&hdr->head, u32_get(&hdr->head) + 1); - if (!u32_get(&hdr->head)) - u32_set(&hdr->head_hi, u32_get(&hdr->head_hi) + 1); - - /* ensure that head change is visible */ - __sync_synchronize(); - - notify = __atomic_exchange_n(&hdr->notify, 0, __ATOMIC_RELAXED); - if (notify) { - struct udebug_client_msg msg = { - .type = CL_MSG_RING_NOTIFY, - .id = buf->id, - .notify_mask = notify, - }; - blob_buf_init(&b, 0); - - udebug_send_msg(buf->ctx, &msg, b.head, -1); - } -} -void udebug_buf_free(struct udebug_buf *buf) -{ - struct udebug *ctx = buf->ctx; - - if (!list_empty(&buf->list) && buf->list.prev) - list_del(&buf->list); - - if (ctx && ctx->fd.fd >= 0) - udebug_buf_msg(buf, CL_MSG_RING_REMOVE); - - munmap(buf->hdr, buf->head_size + 2 * buf->data_size); - close(buf->fd); - memset(buf, 0, sizeof(*buf)); -} - static void -__udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf) +udebug_ubus_req_cb(struct ubus_request *req, int type, struct blob_attr *msg) { - struct udebug_client_msg msg = { - .type = CL_MSG_RING_ADD, - .id = buf->id, - .ring_size = buf->hdr->ring_size, - .data_size = buf->hdr->data_size, - }; - const struct udebug_buf_meta *meta = buf->meta; - void *c; - - blob_buf_init(&b, 0); - blobmsg_add_string(&b, "name", meta->name); - c = blobmsg_open_array(&b, "flags"); - for (size_t i = 0; i < meta->n_flags; i++) { - const struct udebug_buf_flag *flag = &meta->flags[i]; - void *e = blobmsg_open_array(&b, NULL); - blobmsg_add_string(&b, NULL, flag->name); - blobmsg_add_u64(&b, NULL, flag->mask); - blobmsg_close_array(&b, e); - } - blobmsg_close_array(&b, c); - - udebug_send_msg(ctx, &msg, b.head, buf->fd); + udebug_ubus_msg_cb(req->priv, msg); } -int udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf, - const struct udebug_buf_meta *meta) +static bool +udebug_ubus_new_obj_cb(struct ubus_context *ubus, struct ubus_subscriber *sub, + const char *path) { - list_add_tail(&buf->list, &ctx->local_rings); - buf->ctx = ctx; - buf->meta = meta; - buf->id = ctx->next_id++; - buf->hdr->format = meta->format; - buf->hdr->sub_format = meta->sub_format; + struct udebug_ubus *ctx = container_of(sub, struct udebug_ubus, sub); - if (ctx->fd.fd >= 0) - __udebug_buf_add(ctx, buf); + if (strcmp(path, "udebug") != 0) + return false; - return 0; + uloop_timeout_set(&ctx->t, 1); + return true; } -void udebug_init(struct udebug *ctx) +static void udebug_ubus_get_config(struct uloop_timeout *t) { - INIT_LIST_HEAD(&ctx->local_rings); - avl_init(&ctx->remote_rings, udebug_id_cmp, true, NULL); - ctx->fd.fd = -1; - ctx->poll_handle = -1; -} + struct udebug_ubus *ctx = container_of(t, struct udebug_ubus, t); + uint32_t id; -static void udebug_reconnect_cb(struct uloop_timeout *t) -{ - struct udebug *ctx = container_of(t, struct udebug, reconnect); - - if (udebug_connect(ctx, ctx->socket_path) < 0) { - uloop_timeout_set(&ctx->reconnect, 1000); + if (ubus_lookup_id(ctx->ubus, "udebug", &id)) return; - } - udebug_add_uloop(ctx); + ubus_invoke(ctx->ubus, id, "get_config", NULL, udebug_ubus_req_cb, ctx, 1000); } -void udebug_auto_connect(struct udebug *ctx, const char *path) +void udebug_ubus_ring_init(struct udebug *ud, struct udebug_ubus_ring *ring) { - free(ctx->socket_path); - ctx->reconnect.cb = udebug_reconnect_cb; - ctx->socket_path = path ? strdup(path) : NULL; - if (ctx->fd.fd >= 0) - return; - - udebug_reconnect_cb(&ctx->reconnect); + if (!ring->size) + ring->size = ring->default_size; + if (!ring->entries) + ring->entries = ring->default_entries; + udebug_buf_init(ring->buf, ring->entries, ring->size); + udebug_buf_add(ud, ring->buf, ring->meta); } -int udebug_connect(struct udebug *ctx, const char *path) +void udebug_ubus_apply_config(struct udebug *ud, struct udebug_ubus_ring *rings, int n, + struct blob_attr *data, bool enabled) { - struct udebug_remote_buf *rb; - struct udebug_buf *buf; - - if (ctx->fd.fd >= 0) - close(ctx->fd.fd); - ctx->fd.fd = -1; - - if (!path) - path = UDEBUG_SOCK_NAME; + enum { + CFG_ATTR_ENABLE, + CFG_ATTR_SIZE, + CFG_ATTR_ENTRIES, + __CFG_ATTR_MAX, + }; + static struct blobmsg_policy policy[] = { + [CFG_ATTR_ENABLE] = { NULL, BLOBMSG_TYPE_STRING }, + [CFG_ATTR_SIZE] = { NULL, BLOBMSG_TYPE_STRING }, + [CFG_ATTR_ENTRIES] = { NULL, BLOBMSG_TYPE_STRING }, + }; - ctx->fd.fd = usock(USOCK_UNIX, path, NULL); - if (ctx->fd.fd < 0) - return -1; + for (size_t i = 0; i < n; i++) { + struct blob_attr *tb[__CFG_ATTR_MAX], *cur; + struct udebug_buf *buf = rings[i].buf; + const char *name = rings[i].meta->name; + int name_len = strlen(name); + unsigned int size, entries; + bool cur_enabled = enabled; + char *str; + + policy[CFG_ATTR_ENABLE].name = name; + +#define SIZE_FMT "%s_size" + str = alloca(sizeof(SIZE_FMT) + name_len); + sprintf(str, SIZE_FMT, name); + policy[CFG_ATTR_SIZE].name = str; + +#define ENTRIES_FMT "%s_entries" + str = alloca(sizeof(ENTRIES_FMT) + name_len); + sprintf(str, ENTRIES_FMT, name); + policy[CFG_ATTR_ENTRIES].name = str; + + blobmsg_parse_attr(policy, __CFG_ATTR_MAX, tb, data); + + if (enabled && (cur = tb[CFG_ATTR_ENABLE]) != NULL) + cur_enabled = !!atoi(blobmsg_get_string(cur)); + + if ((cur = tb[CFG_ATTR_SIZE]) != NULL) + size = atoi(blobmsg_get_string(cur)); + else + size = rings[i].default_size; + + if ((cur = tb[CFG_ATTR_ENTRIES]) != NULL) + entries = atoi(blobmsg_get_string(cur)); + else + entries = rings[i].default_entries; + + if (udebug_buf_valid(buf) == cur_enabled && + size == rings[i].size && + entries == rings[i].entries) + continue; - list_for_each_entry(buf, &ctx->local_rings, list) - __udebug_buf_add(ctx, buf); + if (udebug_buf_valid(buf)) + udebug_buf_free(buf); - avl_for_each_element(&ctx->remote_rings, rb, node) { - if (!rb->poll) + rings[i].size = size; + rings[i].entries = entries; + if (!cur_enabled) continue; - rb->poll = false; - udebug_remote_buf_set_poll(ctx, rb, true); + udebug_ubus_ring_init(ud, &rings[i]); } - - return 0; } -static bool -udebug_recv_msg(struct udebug *ctx, struct udebug_client_msg *msg, int *fd, - bool wait) +void udebug_netlink_msg(struct udebug_buf *buf, uint16_t proto, const void *data, size_t len) { - struct iovec iov = { - .iov_base = msg, - .iov_len = sizeof(*msg) + struct { + uint16_t pkttype; + uint16_t arphdr; + uint16_t _pad[5]; + uint16_t proto; + } hdr = { + .arphdr = cpu_to_be16(824), + .proto = cpu_to_be16(proto), }; - int ret; - ret = recv_retry(ctx->fd.fd, &iov, wait, fd); - if (ret == -2) - uloop_fd_delete(&ctx->fd); - - return ret == sizeof(*msg); -} - -struct udebug_client_msg *__udebug_poll(struct udebug *ctx, int *fd, bool wait) -{ - static struct udebug_client_msg msg = {}; - - while (udebug_recv_msg(ctx, &msg, fd, wait)) { - struct udebug_remote_buf *rb; - void *key; - - if (msg.type != CL_MSG_RING_NOTIFY) - return &msg; - - if (fd && *fd >= 0) - close(*fd); - - if (!ctx->notify_cb) - continue; - - key = (void *)(uintptr_t)msg.id; - rb = avl_find_element(&ctx->remote_rings, key, rb, node); - if (!rb || !rb->poll) - continue; - - if (ctx->poll_handle >= 0) - __atomic_fetch_or(&rb->buf.hdr->notify, - 1UL << ctx->poll_handle, - __ATOMIC_RELAXED); - ctx->notify_cb(ctx, rb); - } + if (!udebug_buf_valid(buf)) + return; - return NULL; + udebug_entry_init(buf); + udebug_entry_append(buf, &hdr, sizeof(hdr)); + udebug_entry_append(buf, data, len); + udebug_entry_add(buf); } -void udebug_poll(struct udebug *ctx) +void udebug_ubus_init(struct udebug_ubus *ctx, struct ubus_context *ubus, + const char *service, udebug_config_cb cb) { - while (__udebug_poll(ctx, NULL, false)); -} + ctx->ubus = ubus; + ctx->service = service; + ctx->cb = cb; + ctx->sub.new_obj_cb = udebug_ubus_new_obj_cb; + ctx->sub.cb = udebug_ubus_notify_cb; + ubus_register_subscriber(ubus, &ctx->sub); -static void udebug_fd_cb(struct uloop_fd *fd, unsigned int events) -{ - struct udebug *ctx = container_of(fd, struct udebug, fd); - - if (fd->eof) - uloop_fd_delete(fd); - - udebug_poll(ctx); + ctx->t.cb = udebug_ubus_get_config; } -void udebug_add_uloop(struct udebug *ctx) +void udebug_ubus_free(struct udebug_ubus *ctx) { - if (ctx->fd.registered) + if (!ctx->ubus) return; - ctx->fd.cb = udebug_fd_cb; - uloop_fd_add(&ctx->fd, ULOOP_READ); -} - -void __udebug_disconnect(struct udebug *ctx, bool reconnect) -{ - uloop_fd_delete(&ctx->fd); - close(ctx->fd.fd); - ctx->fd.fd = -1; - ctx->poll_handle = -1; - if (ctx->reconnect.cb && reconnect) - uloop_timeout_set(&ctx->reconnect, 1); -} - -void udebug_free(struct udebug *ctx) -{ - struct udebug_remote_buf *rb, *tmp; - struct udebug_buf *buf; - - free(ctx->socket_path); - ctx->socket_path = NULL; - - __udebug_disconnect(ctx, false); - uloop_timeout_cancel(&ctx->reconnect); - - while (!list_empty(&ctx->local_rings)) { - buf = list_first_entry(&ctx->local_rings, struct udebug_buf, list); - udebug_buf_free(buf); - } - - avl_for_each_element_safe(&ctx->remote_rings, rb, node, tmp) - udebug_remote_buf_unmap(ctx, rb); + uloop_timeout_cancel(&ctx->t); + ubus_unregister_subscriber(ctx->ubus, &ctx->sub); }