1 /* 2 * Copyright (C) 2011-2014 Felix Fietkau <nbd@openwrt.org> 3 * 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 7 * 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. 12 */ 13 14 #include <unistd.h> 15 #include <signal.h> 16 17 #include <libubox/blobmsg_json.h> 18 #include "libubus.h" 19 #include "count.h" 20 21 static struct ubus_context *ctx; 22 static struct ubus_subscriber test_event; 23 static struct blob_buf b; 24 25 enum { 26 HELLO_ID, 27 HELLO_MSG, 28 __HELLO_MAX 29 }; 30 31 static const struct blobmsg_policy hello_policy[] = { 32 [HELLO_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, 33 [HELLO_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_STRING }, 34 }; 35 36 struct hello_request { 37 struct ubus_request_data req; 38 struct uloop_timeout timeout; 39 int fd; 40 int idx; 41 char data[]; 42 }; 43 44 static void test_hello_fd_reply(struct uloop_timeout *t) 45 { 46 struct hello_request *req = container_of(t, struct hello_request, timeout); 47 char *data; 48 49 data = alloca(strlen(req->data) + 32); 50 sprintf(data, "msg%d: %s\n", ++req->idx, req->data); 51 if (write(req->fd, data, strlen(data)) < 0) { 52 close(req->fd); 53 free(req); 54 return; 55 } 56 57 uloop_timeout_set(&req->timeout, 1000); 58 } 59 60 static void test_hello_reply(struct uloop_timeout *t) 61 { 62 struct hello_request *req = container_of(t, struct hello_request, timeout); 63 int fds[2]; 64 65 blob_buf_init(&b, 0); 66 blobmsg_add_string(&b, "message", req->data); 67 ubus_send_reply(ctx, &req->req, b.head); 68 69 if (pipe(fds) == -1) { 70 fprintf(stderr, "Failed to create pipe\n"); 71 return; 72 } 73 ubus_request_set_fd(ctx, &req->req, fds[0]); 74 ubus_complete_deferred_request(ctx, &req->req, 0); 75 req->fd = fds[1]; 76 77 req->timeout.cb = test_hello_fd_reply; 78 test_hello_fd_reply(t); 79 } 80 81 static int test_hello(struct ubus_context *ctx, struct ubus_object *obj, 82 struct ubus_request_data *req, const char *method, 83 struct blob_attr *msg) 84 { 85 struct hello_request *hreq; 86 struct blob_attr *tb[__HELLO_MAX]; 87 const char format[] = "%s received a message: %s"; 88 const char *msgstr = "(unknown)"; 89 90 blobmsg_parse(hello_policy, ARRAY_SIZE(hello_policy), tb, blob_data(msg), blob_len(msg)); 91 92 if (tb[HELLO_MSG]) 93 msgstr = blobmsg_data(tb[HELLO_MSG]); 94 95 size_t len = sizeof(*hreq) + sizeof(format) + strlen(obj->name) + strlen(msgstr) + 1; 96 hreq = calloc(1, len); 97 if (!hreq) 98 return UBUS_STATUS_UNKNOWN_ERROR; 99 100 snprintf(hreq->data, len, format, obj->name, msgstr); 101 ubus_defer_request(ctx, req, &hreq->req); 102 hreq->timeout.cb = test_hello_reply; 103 uloop_timeout_set(&hreq->timeout, 1000); 104 105 return 0; 106 } 107 108 enum { 109 WATCH_ID, 110 WATCH_COUNTER, 111 __WATCH_MAX 112 }; 113 114 static const struct blobmsg_policy watch_policy[__WATCH_MAX] = { 115 [WATCH_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, 116 [WATCH_COUNTER] = { .name = "counter", .type = BLOBMSG_TYPE_INT32 }, 117 }; 118 119 static void 120 test_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s, 121 uint32_t id) 122 { 123 fprintf(stderr, "Object %08x went away\n", id); 124 } 125 126 static int 127 test_notify(struct ubus_context *ctx, struct ubus_object *obj, 128 struct ubus_request_data *req, const char *method, 129 struct blob_attr *msg) 130 { 131 #if 0 132 char *str; 133 134 str = blobmsg_format_json(msg, true); 135 fprintf(stderr, "Received notification '%s': %s\n", method, str); 136 free(str); 137 #endif 138 139 return 0; 140 } 141 142 static int test_watch(struct ubus_context *ctx, struct ubus_object *obj, 143 struct ubus_request_data *req, const char *method, 144 struct blob_attr *msg) 145 { 146 struct blob_attr *tb[__WATCH_MAX]; 147 int ret; 148 149 blobmsg_parse(watch_policy, __WATCH_MAX, tb, blob_data(msg), blob_len(msg)); 150 if (!tb[WATCH_ID]) 151 return UBUS_STATUS_INVALID_ARGUMENT; 152 153 test_event.remove_cb = test_handle_remove; 154 test_event.cb = test_notify; 155 ret = ubus_subscribe(ctx, &test_event, blobmsg_get_u32(tb[WATCH_ID])); 156 fprintf(stderr, "Watching object %08x: %s\n", blobmsg_get_u32(tb[WATCH_ID]), ubus_strerror(ret)); 157 return ret; 158 } 159 160 enum { 161 COUNT_TO, 162 COUNT_STRING, 163 __COUNT_MAX 164 }; 165 166 static const struct blobmsg_policy count_policy[__COUNT_MAX] = { 167 [COUNT_TO] = { .name = "to", .type = BLOBMSG_TYPE_INT32 }, 168 [COUNT_STRING] = { .name = "string", .type = BLOBMSG_TYPE_STRING }, 169 }; 170 171 static int test_count(struct ubus_context *ctx, struct ubus_object *obj, 172 struct ubus_request_data *req, const char *method, 173 struct blob_attr *msg) 174 { 175 struct blob_attr *tb[__COUNT_MAX]; 176 char *s1, *s2; 177 uint32_t num; 178 179 blobmsg_parse(count_policy, __COUNT_MAX, tb, blob_data(msg), blob_len(msg)); 180 if (!tb[COUNT_TO] || !tb[COUNT_STRING]) 181 return UBUS_STATUS_INVALID_ARGUMENT; 182 183 num = blobmsg_get_u32(tb[COUNT_TO]); 184 s1 = blobmsg_get_string(tb[COUNT_STRING]); 185 s2 = count_to_number(num); 186 if (!s1 || !s2) { 187 free(s2); 188 return UBUS_STATUS_UNKNOWN_ERROR; 189 } 190 blob_buf_init(&b, 0); 191 blobmsg_add_u32(&b, "rc", strcmp(s1, s2)); 192 ubus_send_reply(ctx, req, b.head); 193 free(s2); 194 195 return 0; 196 } 197 198 static const struct ubus_method test_methods[] = { 199 UBUS_METHOD("hello", test_hello, hello_policy), 200 UBUS_METHOD("watch", test_watch, watch_policy), 201 UBUS_METHOD("count", test_count, count_policy), 202 }; 203 204 static struct ubus_object_type test_object_type = 205 UBUS_OBJECT_TYPE("test", test_methods); 206 207 static struct ubus_object test_object = { 208 .name = "test", 209 .type = &test_object_type, 210 .methods = test_methods, 211 .n_methods = ARRAY_SIZE(test_methods), 212 }; 213 214 static void server_main(void) 215 { 216 int ret; 217 218 ret = ubus_add_object(ctx, &test_object); 219 if (ret) 220 fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret)); 221 222 ret = ubus_register_subscriber(ctx, &test_event); 223 if (ret) 224 fprintf(stderr, "Failed to add watch handler: %s\n", ubus_strerror(ret)); 225 226 uloop_run(); 227 } 228 229 int main(int argc, char **argv) 230 { 231 const char *ubus_socket = NULL; 232 int ch; 233 234 while ((ch = getopt(argc, argv, "cs:")) != -1) { 235 switch (ch) { 236 case 's': 237 ubus_socket = optarg; 238 break; 239 default: 240 break; 241 } 242 } 243 244 uloop_init(); 245 signal(SIGPIPE, SIG_IGN); 246 247 ctx = ubus_connect(ubus_socket); 248 if (!ctx) { 249 fprintf(stderr, "Failed to connect to ubus\n"); 250 return -1; 251 } 252 253 ubus_add_uloop(ctx); 254 255 server_main(); 256 257 ubus_free(ctx); 258 uloop_done(); 259 260 return 0; 261 } 262
This page was automatically generated by LXR 0.3.1. • OpenWrt