Import ubus tools.

This commit is contained in:
2016-02-26 22:16:27 +01:00
parent 2c3ca52e41
commit 6bc8cdeef3
200 changed files with 23469 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 2.6)
ADD_DEFINITIONS(-I..)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..)
IF (BUILD_EXAMPLES)
ADD_EXECUTABLE(server server.c count.c)
TARGET_LINK_LIBRARIES(server ubus ubox blobmsg_json)
ADD_EXECUTABLE(client client.c count.c)
TARGET_LINK_LIBRARIES(client ubus ubox)
ENDIF()

239
3P/ubus/examples/client.c Normal file
View File

@@ -0,0 +1,239 @@
/*
* Copyright (C) 2011 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 <sys/time.h>
#include <unistd.h>
#include <libubox/ustream.h>
#include "libubus.h"
#include "count.h"
static struct ubus_context *ctx;
static struct blob_buf b;
static void test_client_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
{
fprintf(stderr, "Subscribers active: %d\n", obj->has_subscribers);
}
static struct ubus_object test_client_object = {
.subscribe_cb = test_client_subscribe_cb,
};
static void test_client_notify_cb(struct uloop_timeout *timeout)
{
static int counter = 0;
int err;
struct timeval tv1, tv2;
int max = 1000;
long delta;
int i = 0;
blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "counter", counter++);
gettimeofday(&tv1, NULL);
for (i = 0; i < max; i++)
err = ubus_notify(ctx, &test_client_object, "ping", b.head, 1000);
gettimeofday(&tv2, NULL);
if (err)
fprintf(stderr, "Notify failed: %s\n", ubus_strerror(err));
delta = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
fprintf(stderr, "Avg time per iteration: %ld usec\n", delta / max);
uloop_timeout_set(timeout, 1000);
}
enum {
RETURN_CODE,
__RETURN_MAX,
};
static const struct blobmsg_policy return_policy[__RETURN_MAX] = {
[RETURN_CODE] = { .name = "rc", .type = BLOBMSG_TYPE_INT32 },
};
static void test_count_data_cb(struct ubus_request *req,
int type, struct blob_attr *msg)
{
struct blob_attr *tb[__RETURN_MAX];
int rc;
uint32_t count_to = *(uint32_t *)req->priv;
blobmsg_parse(return_policy, __RETURN_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[RETURN_CODE]) {
fprintf(stderr, "No return code received from server\n");
return;
}
rc = blobmsg_get_u32(tb[RETURN_CODE]);
if (rc)
fprintf(stderr, "Corruption of data with count up to '%u'\n", count_to);
else
fprintf(stderr, "Server validated our count up to '%u'\n", count_to);
}
static void test_count(struct uloop_timeout *timeout)
{
enum {
COUNT_TO_MIN = 10000,
COUNT_TO_MAX = 1000000,
PROGRESSION = 100,
};
uint32_t id;
static uint32_t count_to = 100000;
static int count_progression = PROGRESSION;
char *s;
if (count_to <= COUNT_TO_MIN)
count_progression = PROGRESSION;
else if (count_to >= COUNT_TO_MAX)
count_progression = -PROGRESSION;
count_to += count_progression;
s = count_to_number(count_to);
if (!s)
fprintf(stderr, "Could not allocate memory to count up to '%u'\n", count_to);
fprintf(stderr, "Sending count up to '%u'; string has length '%u'\n",
count_to, (uint32_t)strlen(s));
blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "to", count_to);
blobmsg_add_string(&b, "string", s);
if (ubus_lookup_id(ctx, "test", &id)) {
fprintf(stderr, "Failed to look up test object\n");
return;
}
ubus_invoke(ctx, id, "count", b.head, test_count_data_cb, &count_to, 5000);
free(s);
uloop_timeout_set(timeout, 2000);
}
static struct uloop_timeout notify_timer = {
.cb = test_client_notify_cb,
};
static struct uloop_timeout count_timer = {
.cb = test_count,
};
static void test_client_fd_data_cb(struct ustream *s, int bytes)
{
char *data, *sep;
int len;
data = ustream_get_read_buf(s, &len);
if (len < 1)
return;
sep = strchr(data, '\n');
if (!sep)
return;
*sep = 0;
fprintf(stderr, "Got line: %s\n", data);
ustream_consume(s, sep + 1 - data);
}
static void test_client_fd_cb(struct ubus_request *req, int fd)
{
static struct ustream_fd test_fd;
fprintf(stderr, "Got fd from the server, watching...\n");
test_fd.stream.notify_read = test_client_fd_data_cb;
ustream_fd_init(&test_fd, fd);
}
static void test_client_complete_cb(struct ubus_request *req, int ret)
{
fprintf(stderr, "completed request, ret: %d\n", ret);
}
static void client_main(void)
{
static struct ubus_request req;
uint32_t id;
int ret;
ret = ubus_add_object(ctx, &test_client_object);
if (ret) {
fprintf(stderr, "Failed to add_object object: %s\n", ubus_strerror(ret));
return;
}
if (ubus_lookup_id(ctx, "test", &id)) {
fprintf(stderr, "Failed to look up test object\n");
return;
}
blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "id", test_client_object.id);
ubus_invoke(ctx, id, "watch", b.head, NULL, 0, 3000);
test_client_notify_cb(&notify_timer);
blob_buf_init(&b, 0);
blobmsg_add_string(&b, "msg", "blah");
ubus_invoke_async(ctx, id, "hello", b.head, &req);
req.fd_cb = test_client_fd_cb;
req.complete_cb = test_client_complete_cb;
ubus_complete_request_async(ctx, &req);
uloop_timeout_set(&count_timer, 2000);
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();
ctx = ubus_connect(ubus_socket);
if (!ctx) {
fprintf(stderr, "Failed to connect to ubus\n");
return -1;
}
ubus_add_uloop(ctx);
client_main();
ubus_free(ctx);
uloop_done();
return 0;
}

48
3P/ubus/examples/count.c Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2011 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 <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "count.h"
char *count_to_number(uint32_t num)
{
uint32_t ptr = 0, size = 0;
uint32_t written = 0, i;
int new_line_every_n_numbers = 30;
char *s;
for (i=0; i < num; ++i) {
size += snprintf(NULL, 0, "%u ", i);
if (i > 0 && i % new_line_every_n_numbers == 0)
size++;
}
size++; /* one for null char */
s = calloc(size, sizeof(char));
if (!s)
goto out;
for (i=0; i < num; ++i) {
written = sprintf(&s[ptr], "%u ", i);
ptr += written;
if (i > 0 && i % new_line_every_n_numbers == 0) {
sprintf(&s[ptr], "\n");
ptr++;
}
}
out:
return s;
}

19
3P/ubus/examples/count.h Normal file
View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2011 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.
*/
#ifndef __COUNT_H
#define __COUNT_H
char *count_to_number(uint32_t num);
#endif

260
3P/ubus/examples/server.c Normal file
View File

@@ -0,0 +1,260 @@
/*
* 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);
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;
}