Ubus
OpenWrt system message/RPC bus.
server.c
Go to the documentation of this file.
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 {
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]);
75  req->fd = fds[1];
76 
77  req->timeout.cb = test_hello_fd_reply;
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)
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 {
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
121  uint32_t id)
122 {
123  fprintf(stderr, "Object %08x went away\n", id);
124 }
125 
126 static int
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])
152 
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 {
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])
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);
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[] = {
202 };
203 
204 static struct ubus_object_type test_object_type =
206 
207 static struct ubus_object test_object = {
208  .name = "test",
209  .type = &test_object_type,
211  .n_methods = ARRAY_SIZE(test_methods),
212 };
213 
214 static void server_main(void)
215 {
216  int ret;
217 
219  if (ret)
220  fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret));
221 
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 
254 
255  server_main();
256 
257  ubus_free(ctx);
258  uloop_done();
259 
260  return 0;
261 }
static int timeout
Definition: cli.c:21
char * count_to_number(uint32_t num)
Definition: count.c:19
int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj)
Definition: libubus-obj.c:209
void ubus_complete_deferred_request(struct ubus_context *ctx, struct ubus_request_data *req, int ret)
Definition: libubus-req.c:189
int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req, struct blob_attr *msg)
Definition: libubus-req.c:205
int ubus_subscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id)
Definition: libubus-sub.c:118
int ubus_register_subscriber(struct ubus_context *ctx, struct ubus_subscriber *s)
Definition: libubus-sub.c:77
struct ubus_context * ubus_connect(const char *path)
Definition: libubus.c:351
void ubus_free(struct ubus_context *ctx)
Definition: libubus.c:378
const char * ubus_strerror(int error)
Definition: libubus.c:59
static void ubus_defer_request(struct ubus_context *ctx, struct ubus_request_data *req, struct ubus_request_data *new_req)
Definition: libubus.h:375
#define UBUS_OBJECT_TYPE(_name, _methods)
Definition: libubus.h:68
static void ubus_request_set_fd(struct ubus_context *ctx, struct ubus_request_data *req, int fd)
Definition: libubus.h:384
static void ubus_add_uloop(struct ubus_context *ctx)
Definition: libubus.h:268
#define UBUS_METHOD(_name, _handler, _policy)
Definition: libubus.h:86
static struct ubus_object_type test_object_type
Definition: server.c:204
static const struct blobmsg_policy count_policy[__COUNT_MAX]
Definition: server.c:166
int main(int argc, char **argv)
Definition: server.c:229
static void test_hello_fd_reply(struct uloop_timeout *t)
Definition: server.c:44
static struct ubus_object test_object
Definition: server.c:207
static struct ubus_context * ctx
Definition: server.c:21
static int test_count(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
Definition: server.c:171
static struct blob_buf b
Definition: server.c:23
static const struct blobmsg_policy watch_policy[__WATCH_MAX]
Definition: server.c:114
@ HELLO_MSG
Definition: server.c:27
@ __HELLO_MAX
Definition: server.c:28
@ HELLO_ID
Definition: server.c:26
static int test_notify(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
Definition: server.c:127
static struct ubus_subscriber test_event
Definition: server.c:22
@ WATCH_ID
Definition: server.c:109
@ WATCH_COUNTER
Definition: server.c:110
@ __WATCH_MAX
Definition: server.c:111
static const struct blobmsg_policy hello_policy[]
Definition: server.c:31
static const struct ubus_method test_methods[]
Definition: server.c:198
static void server_main(void)
Definition: server.c:214
static int test_hello(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
Definition: server.c:81
static void test_hello_reply(struct uloop_timeout *t)
Definition: server.c:60
@ __COUNT_MAX
Definition: server.c:163
@ COUNT_TO
Definition: server.c:161
@ COUNT_STRING
Definition: server.c:162
static int test_watch(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
Definition: server.c:142
static void test_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s, uint32_t id)
Definition: server.c:120
struct ubus_request_data req
Definition: server.c:37
char data[]
Definition: server.c:41
struct uloop_timeout timeout
Definition: server.c:38
const struct ubus_method * methods
Definition: libubus.h:122
const char * name
Definition: libubus.h:129
ubus_remove_handler_t remove_cb
Definition: libubus.h:147
ubus_handler_t cb
Definition: libubus.h:146
@ UBUS_STATUS_INVALID_ARGUMENT
Definition: ubusmsg.h:121
@ UBUS_STATUS_UNKNOWN_ERROR
Definition: ubusmsg.h:128