diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3d06161..0279f6e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,9 +4,9 @@ ADD_DEFINITIONS(-I..) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..) IF (BUILD_EXAMPLES) - ADD_EXECUTABLE(server server.c) + ADD_EXECUTABLE(server server.c count.c) TARGET_LINK_LIBRARIES(server ubus ubox blobmsg_json) - ADD_EXECUTABLE(client client.c) + ADD_EXECUTABLE(client client.c count.c) TARGET_LINK_LIBRARIES(client ubus ubox) ENDIF() diff --git a/examples/client.c b/examples/client.c index 4d6b6ec..b586eaf 100644 --- a/examples/client.c +++ b/examples/client.c @@ -17,6 +17,7 @@ #include <libubox/ustream.h> #include "libubus.h" +#include "count.h" static struct ubus_context *ctx; static struct blob_buf b; @@ -55,10 +56,85 @@ static void test_client_notify_cb(struct uloop_timeout *timeout) 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; @@ -121,6 +197,8 @@ static void client_main(void) req.complete_cb = test_client_complete_cb; ubus_complete_request_async(ctx, &req); + uloop_timeout_set(&count_timer, 2000); + uloop_run(); } diff --git a/examples/count.c b/examples/count.c new file mode 100644 index 0000000..e3e9c8a --- /dev/null +++ b/examples/count.c @@ -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; +} diff --git a/examples/count.h b/examples/count.h new file mode 100644 index 0000000..1f90f21 --- /dev/null +++ b/examples/count.h @@ -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 diff --git a/examples/server.c b/examples/server.c index 95eba5e..bbb3347 100644 --- a/examples/server.c +++ b/examples/server.c @@ -16,6 +16,7 @@ #include <libubox/blobmsg_json.h> #include "libubus.h" +#include "count.h" static struct ubus_context *ctx; static struct ubus_subscriber test_event; @@ -149,9 +150,48 @@ static int test_watch(struct ubus_context *ctx, struct ubus_object *obj, 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 =