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.
14 #include <sys/types.h>
16 #include <sys/socket.h>
22 #include <libubox/usock.h>
23 #include <libubox/blob.h>
24 #include <libubox/blobmsg.h>
27 #include "libubus-internal.h"
29 #define STATIC_IOV(_var) { .iov_base = (char *) &(_var), .iov_len = sizeof(_var) }
31 static const struct blob_attr_info ubus_policy
[UBUS_ATTR_MAX
] = {
32 [UBUS_ATTR_STATUS
] = { .type
= BLOB_ATTR_INT32
},
33 [UBUS_ATTR_OBJID
] = { .type
= BLOB_ATTR_INT32
},
34 [UBUS_ATTR_OBJPATH
] = { .type
= BLOB_ATTR_STRING
},
35 [UBUS_ATTR_METHOD
] = { .type
= BLOB_ATTR_STRING
},
36 [UBUS_ATTR_ACTIVE
] = { .type
= BLOB_ATTR_INT8
},
37 [UBUS_ATTR_NO_REPLY
] = { .type
= BLOB_ATTR_INT8
},
38 [UBUS_ATTR_SUBSCRIBERS
] = { .type
= BLOB_ATTR_NESTED
},
41 static struct blob_attr
*attrbuf
[UBUS_ATTR_MAX
];
43 __hidden
struct blob_attr
**ubus_parse_msg(struct blob_attr
*msg
)
45 blob_parse(msg
, attrbuf
, ubus_policy
, UBUS_ATTR_MAX
);
49 static void wait_data(int fd
, bool write
)
51 struct pollfd pfd
= { .fd
= fd
};
53 pfd
.events
= write
? POLLOUT
: POLLIN
;
57 static int writev_retry(int fd
, struct iovec
*iov
, int iov_len
)
62 int cur_len
= writev(fd
, iov
, iov_len
);
76 while (cur_len
>= iov
->iov_len
) {
77 cur_len
-= iov
->iov_len
;
80 if (!cur_len
|| !iov_len
)
83 iov
->iov_len
-= cur_len
;
87 int __hidden
ubus_send_msg(struct ubus_context
*ctx
, uint32_t seq
,
88 struct blob_attr
*msg
, int cmd
, uint32_t peer
)
90 struct ubus_msghdr hdr
;
91 struct iovec iov
[2] = {
101 blob_buf_init(&b
, 0);
105 iov
[1].iov_base
= (char *) msg
;
106 iov
[1].iov_len
= blob_raw_len(msg
);
108 return writev_retry(ctx
->sock
.fd
, iov
, ARRAY_SIZE(iov
));
111 static bool recv_retry(int fd
, struct iovec
*iov
, bool wait
)
115 while (iov
->iov_len
> 0) {
117 wait_data(fd
, false);
119 bytes
= read(fd
, iov
->iov_base
, iov
->iov_len
);
134 iov
->iov_len
-= bytes
;
135 iov
->iov_base
+= bytes
;
141 static bool ubus_validate_hdr(struct ubus_msghdr
*hdr
)
143 if (hdr
->version
!= 0)
146 if (blob_raw_len(hdr
->data
) < sizeof(*hdr
->data
))
149 if (blob_pad_len(hdr
->data
) > UBUS_MAX_MSGLEN
)
155 static bool get_next_msg(struct ubus_context
*ctx
)
157 struct iovec iov
= STATIC_IOV(ctx
->msgbuf
.hdr
);
159 /* receive header + start attribute */
160 iov
.iov_len
+= sizeof(struct blob_attr
);
161 if (!recv_retry(ctx
->sock
.fd
, &iov
, false))
164 iov
.iov_len
= blob_len(ctx
->msgbuf
.hdr
.data
);
165 if (iov
.iov_len
> 0 && !recv_retry(ctx
->sock
.fd
, &iov
, true))
168 return ubus_validate_hdr(&ctx
->msgbuf
.hdr
);
171 void __hidden
ubus_handle_data(struct uloop_fd
*u
, unsigned int events
)
173 struct ubus_context
*ctx
= container_of(u
, struct ubus_context
, sock
);
174 struct ubus_msghdr
*hdr
= &ctx
->msgbuf
.hdr
;
176 while (get_next_msg(ctx
)) {
177 ubus_process_msg(ctx
, hdr
);
183 ctx
->connection_lost(ctx
);
187 ubus_refresh_state(struct ubus_context
*ctx
)
189 struct ubus_object
*obj
, *tmp
;
191 /* clear all type IDs, they need to be registered again */
192 avl_for_each_element(&ctx
->objects
, obj
, avl
)
196 /* push out all objects again */
197 avl_for_each_element_safe(&ctx
->objects
, obj
, avl
, tmp
) {
199 avl_delete(&ctx
->objects
, &obj
->avl
);
200 ubus_add_object(ctx
, obj
);
204 int ubus_reconnect(struct ubus_context
*ctx
, const char *path
)
207 struct ubus_msghdr hdr
;
208 struct blob_attr data
;
210 struct blob_attr
*buf
;
211 int ret
= UBUS_STATUS_UNKNOWN_ERROR
;
214 path
= UBUS_UNIX_SOCKET
;
216 if (ctx
->sock
.fd
>= 0) {
217 if (ctx
->sock
.registered
)
218 uloop_fd_delete(&ctx
->sock
);
223 ctx
->sock
.fd
= usock(USOCK_UNIX
, path
, NULL
);
224 if (ctx
->sock
.fd
< 0)
225 return UBUS_STATUS_CONNECTION_FAILED
;
227 if (read(ctx
->sock
.fd
, &hdr
, sizeof(hdr
)) != sizeof(hdr
))
230 if (!ubus_validate_hdr(&hdr
.hdr
))
233 if (hdr
.hdr
.type
!= UBUS_MSG_HELLO
)
236 buf
= calloc(1, blob_raw_len(&hdr
.data
));
240 memcpy(buf
, &hdr
.data
, sizeof(hdr
.data
));
241 if (read(ctx
->sock
.fd
, blob_data(buf
), blob_len(buf
)) != blob_len(buf
))
244 ctx
->local_id
= hdr
.hdr
.peer
;
248 ret
= UBUS_STATUS_OK
;
249 fcntl(ctx
->sock
.fd
, F_SETFL
, fcntl(ctx
->sock
.fd
, F_GETFL
) | O_NONBLOCK
);
251 ubus_refresh_state(ctx
);