123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- /*
- * Copyright (C) 2011-2014 Felix Fietkau <nbd@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1
- * as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include <unistd.h>
- #include <signal.h>
- #include <libubox/blobmsg_json.h>
- #include "libubus.h"
- #include "count.h"
- static struct ubus_context *ctx;
- static struct ubus_subscriber test_event;
- static struct blob_buf b;
- enum {
- HELLO_ID,
- HELLO_MSG,
- __HELLO_MAX
- };
- static const struct blobmsg_policy hello_policy[] = {
- [HELLO_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
- [HELLO_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_STRING },
- };
- struct hello_request {
- struct ubus_request_data req;
- struct uloop_timeout timeout;
- int fd;
- int idx;
- char data[];
- };
- static void test_hello_fd_reply(struct uloop_timeout *t)
- {
- struct hello_request *req = container_of(t, struct hello_request, timeout);
- char *data;
- data = alloca(strlen(req->data) + 32);
- sprintf(data, "msg%d: %s\n", ++req->idx, req->data);
- if (write(req->fd, data, strlen(data)) < 0) {
- close(req->fd);
- free(req);
- return;
- }
- uloop_timeout_set(&req->timeout, 1000);
- }
- static void test_hello_reply(struct uloop_timeout *t)
- {
- struct hello_request *req = container_of(t, struct hello_request, timeout);
- int fds[2];
- blob_buf_init(&b, 0);
- blobmsg_add_string(&b, "message", req->data);
- ubus_send_reply(ctx, &req->req, b.head);
- if (pipe(fds) == -1) {
- fprintf(stderr, "Failed to create pipe\n");
- return;
- }
- ubus_request_set_fd(ctx, &req->req, fds[0]);
- ubus_complete_deferred_request(ctx, &req->req, 0);
- req->fd = fds[1];
- req->timeout.cb = test_hello_fd_reply;
- test_hello_fd_reply(t);
- }
- static int test_hello(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
- {
- struct hello_request *hreq;
- struct blob_attr *tb[__HELLO_MAX];
- const char *format = "%s received a message: %s";
- const char *msgstr = "(unknown)";
- blobmsg_parse(hello_policy, ARRAY_SIZE(hello_policy), tb, blob_data(msg), blob_len(msg));
- if (tb[HELLO_MSG])
- msgstr = blobmsg_data(tb[HELLO_MSG]);
- hreq = calloc(1, sizeof(*hreq) + strlen(format) + strlen(obj->name) + strlen(msgstr) + 1);
- if (!hreq)
- return UBUS_STATUS_UNKNOWN_ERROR;
- sprintf(hreq->data, format, obj->name, msgstr);
- ubus_defer_request(ctx, req, &hreq->req);
- hreq->timeout.cb = test_hello_reply;
- uloop_timeout_set(&hreq->timeout, 1000);
- return 0;
- }
- enum {
- WATCH_ID,
- WATCH_COUNTER,
- __WATCH_MAX
- };
- static const struct blobmsg_policy watch_policy[__WATCH_MAX] = {
- [WATCH_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
- [WATCH_COUNTER] = { .name = "counter", .type = BLOBMSG_TYPE_INT32 },
- };
- static void
- test_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s,
- uint32_t id)
- {
- fprintf(stderr, "Object %08x went away\n", id);
- }
- static int
- test_notify(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
- {
- #if 0
- char *str;
- str = blobmsg_format_json(msg, true);
- fprintf(stderr, "Received notification '%s': %s\n", method, str);
- free(str);
- #endif
- return 0;
- }
- static int test_watch(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
- {
- struct blob_attr *tb[__WATCH_MAX];
- int ret;
- blobmsg_parse(watch_policy, __WATCH_MAX, tb, blob_data(msg), blob_len(msg));
- if (!tb[WATCH_ID])
- return UBUS_STATUS_INVALID_ARGUMENT;
- test_event.remove_cb = test_handle_remove;
- test_event.cb = test_notify;
- ret = ubus_subscribe(ctx, &test_event, blobmsg_get_u32(tb[WATCH_ID]));
- fprintf(stderr, "Watching object %08x: %s\n", blobmsg_get_u32(tb[WATCH_ID]), ubus_strerror(ret));
- return ret;
- }
- enum {
- COUNT_TO,
- COUNT_STRING,
- __COUNT_MAX
- };
- static const struct blobmsg_policy count_policy[__COUNT_MAX] = {
- [COUNT_TO] = { .name = "to", .type = BLOBMSG_TYPE_INT32 },
- [COUNT_STRING] = { .name = "string", .type = BLOBMSG_TYPE_STRING },
- };
- static int test_count(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
- {
- struct blob_attr *tb[__COUNT_MAX];
- char *s1, *s2;
- uint32_t num;
- blobmsg_parse(count_policy, __COUNT_MAX, tb, blob_data(msg), blob_len(msg));
- if (!tb[COUNT_TO] || !tb[COUNT_STRING])
- return UBUS_STATUS_INVALID_ARGUMENT;
- num = blobmsg_get_u32(tb[COUNT_TO]);
- s1 = blobmsg_get_string(tb[COUNT_STRING]);
- s2 = count_to_number(num);
- if (!s1 || !s2) {
- free(s2);
- return UBUS_STATUS_UNKNOWN_ERROR;
- }
- blob_buf_init(&b, 0);
- blobmsg_add_u32(&b, "rc", strcmp(s1, s2));
- ubus_send_reply(ctx, req, b.head);
- free(s2);
- return 0;
- }
- static const struct ubus_method test_methods[] = {
- UBUS_METHOD("hello", test_hello, hello_policy),
- UBUS_METHOD("watch", test_watch, watch_policy),
- UBUS_METHOD("count", test_count, count_policy),
- };
- static struct ubus_object_type test_object_type =
- UBUS_OBJECT_TYPE("test", test_methods);
- static struct ubus_object test_object = {
- .name = "test",
- .type = &test_object_type,
- .methods = test_methods,
- .n_methods = ARRAY_SIZE(test_methods),
- };
- static void server_main(void)
- {
- int ret;
- ret = ubus_add_object(ctx, &test_object);
- if (ret)
- fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret));
- ret = ubus_register_subscriber(ctx, &test_event);
- if (ret)
- fprintf(stderr, "Failed to add watch handler: %s\n", ubus_strerror(ret));
- uloop_run();
- }
- int main(int argc, char **argv)
- {
- const char *ubus_socket = NULL;
- int ch;
- while ((ch = getopt(argc, argv, "cs:")) != -1) {
- switch (ch) {
- case 's':
- ubus_socket = optarg;
- break;
- default:
- break;
- }
- }
- argc -= optind;
- argv += optind;
- uloop_init();
- signal(SIGPIPE, SIG_IGN);
- ctx = ubus_connect(ubus_socket);
- if (!ctx) {
- fprintf(stderr, "Failed to connect to ubus\n");
- return -1;
- }
- ubus_add_uloop(ctx);
- server_main();
- ubus_free(ctx);
- uloop_done();
- return 0;
- }
|