-static int ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
- struct blob_attr *msg, int cmd, uint32_t peer)
-{
- struct ubus_msghdr hdr;
- struct iovec iov[2] = {
- STATIC_IOV(hdr)
- };
-
- hdr.version = 0;
- hdr.type = cmd;
- hdr.seq = seq;
- hdr.peer = peer;
-
- if (!msg) {
- blob_buf_init(&b, 0);
- msg = b.head;
- }
-
- iov[1].iov_base = (char *) msg;
- iov[1].iov_len = blob_raw_len(msg);
-
- return writev(ctx->sock.fd, iov, 2);
-}
-
-static int ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
- struct blob_attr *msg, int cmd, uint32_t peer)
-{
- memset(req, 0, sizeof(*req));
-
- INIT_LIST_HEAD(&req->list);
- INIT_LIST_HEAD(&req->pending);
- req->ctx = ctx;
- req->peer = peer;
- req->seq = ++ctx->request_seq;
- return ubus_send_msg(ctx, req->seq, msg, cmd, peer);
-}
-
-static bool recv_retry(int fd, struct iovec *iov, bool wait)
-{
- int bytes;
-
- while (iov->iov_len > 0) {
- bytes = read(fd, iov->iov_base, iov->iov_len);
- if (bytes < 0) {
- bytes = 0;
- if (errno == EINTR)
- continue;
-
- if (errno != EAGAIN) {
- perror("read");
- return false;
- }
- }
- if (!wait && !bytes)
- return false;
-
- wait = true;
- iov->iov_len -= bytes;
- iov->iov_base += bytes;
- }
-
- return true;
-}
-
-static bool ubus_validate_hdr(struct ubus_msghdr *hdr)
-{
- if (hdr->version != 0)
- return false;
-
- if (blob_raw_len(hdr->data) < sizeof(*hdr->data))
- return false;
-
- if (blob_raw_len(hdr->data) + sizeof(*hdr) > UBUS_MAX_MSGLEN)
- return false;
-
- return true;
-}
-
-static bool get_next_msg(struct ubus_context *ctx, bool wait)
-{
- struct iovec iov = STATIC_IOV(ctx->msgbuf.hdr);
-
- /* receive header + start attribute */
- iov.iov_len += sizeof(struct blob_attr);
- if (!recv_retry(ctx->sock.fd, &iov, wait))
- return false;
-
- iov.iov_len = blob_len(ctx->msgbuf.hdr.data);
- if (iov.iov_len > 0 && !recv_retry(ctx->sock.fd, &iov, true))
- return false;
-
- return ubus_validate_hdr(&ctx->msgbuf.hdr);
-}
-
-static bool ubus_get_status(struct ubus_msghdr *hdr, int *ret)
-{
- ubus_parse_msg(hdr->data);
-
- if (!attrbuf[UBUS_ATTR_STATUS])
- return false;
-
- *ret = blob_get_int32(attrbuf[UBUS_ATTR_STATUS]);
- return true;
-}
-
-static void req_data_cb(struct ubus_request *req, int type, struct blob_attr *data)
-{
- struct blob_attr **attr;
-
- if (req->raw_data_cb)
- req->raw_data_cb(req, type, data);
-
- if (!req->data_cb)
- return;
-
- attr = ubus_parse_msg(data);
- req->data_cb(req, type, attr[UBUS_ATTR_DATA]);
-}
-
-static void ubus_process_req_data(struct ubus_request *req)
-{
- struct ubus_pending_data *data;
-
- while (!list_empty(&req->pending)) {
- data = list_first_entry(&req->pending,
- struct ubus_pending_data, list);
- list_del(&data->list);
- if (!req->cancelled)
- req_data_cb(req, data->type, data->data);
- free(data);
- }
-}
-
-static void ubus_req_complete_cb(struct ubus_request *req)
-{
- ubus_complete_handler_t cb = req->complete_cb;
-
- if (!cb)
- return;
-
- req->complete_cb = NULL;
- cb(req, req->status_code);
-}
-
-static int ubus_process_req_status(struct ubus_request *req, struct ubus_msghdr *hdr)