summaryrefslogtreecommitdiff
path: root/libubus.h
blob: c93ad8f8a7541575681b6d92197f948accf99f9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <libubox/avl.h>
#include <libubox/list.h>
#include <libubox/blobmsg.h>
#include <libubox/uloop.h>
#include <stdint.h>
#include "ubusmsg.h"
#include "ubus_common.h"

struct ubus_context;
struct ubus_msg_src;
struct ubus_object;
struct ubus_request;
struct ubus_request_data;
struct ubus_object_data;

typedef void (*ubus_lookup_handler_t)(struct ubus_context *ctx,
				      struct ubus_object_data *obj,
				      void *priv);
typedef int (*ubus_handler_t)(struct ubus_context *ctx, struct ubus_object *obj,
			      struct ubus_request_data *req,
			      const char *method, struct blob_attr *msg);
typedef void (*ubus_data_handler_t)(struct ubus_request *req,
				    int type, struct blob_attr *msg);
typedef void (*ubus_complete_handler_t)(struct ubus_request *req, int ret);


#define UBUS_SIGNATURE(_type, _name)	{ .type = _type, .name = _name }

#define UBUS_METHOD_START(_name)		UBUS_SIGNATURE(UBUS_SIGNATURE_METHOD, _name)
#define UBUS_METHOD_END()			UBUS_SIGNATURE(UBUS_SIGNATURE_END, NULL)

#define UBUS_FIELD(_type, _name)		UBUS_SIGNATURE(BLOBMSG_TYPE_ ## _type, _name)

#define UBUS_ARRAY(_name)			UBUS_FIELD(ARRAY, _name)
#define UBUS_ARRAY_END()			UBUS_SIGNATURE(UBUS_SIGNATURE_END, NULL)

#define UBUS_TABLE_START(_name)			UBUS_FIELD(TABLE, _name)
#define UBUS_TABLE_END()			UBUS_SIGNATURE(UBUS_SIGNATURE_END, NULL)

#define UBUS_OBJECT_TYPE(_name, _signature)		\
	{						\
		.name = _name,				\
		.id = 0,				\
		.n_signature = ARRAY_SIZE(_signature),	\
		.signature = _signature			\
	}

struct ubus_signature {
	enum blobmsg_type type;
	const char *name;
};

struct ubus_object_type {
	const char *name;
	uint32_t id;
	int n_signature;
	const struct ubus_signature *signature;
};

struct ubus_method {
	const char *name;
	ubus_handler_t handler;
};

struct ubus_object {
	struct avl_node avl;

	const char *name;
	uint32_t id;

	const char *path;
	struct ubus_object_type *type;

	const struct ubus_method *methods;
	int n_methods;
};

struct ubus_context {
	struct list_head requests;
	struct avl_tree objects;

	struct uloop_fd sock;

	uint32_t local_id;
	uint32_t request_seq;

	void (*connection_lost)(struct ubus_context *ctx);

	struct {
		struct ubus_msghdr hdr;
		char data[UBUS_MAX_MSGLEN - sizeof(struct ubus_msghdr)];
	} msgbuf;
};

struct ubus_object_data {
	uint32_t id;
	uint32_t type_id;
	const char *path;
	struct blob_attr *signature;
};

struct ubus_request_data {
	uint32_t object;
	uint32_t peer;
	uint32_t seq;
};

struct ubus_request {
	struct list_head list;

	struct list_head pending;
	bool status_msg;
	int status_code;
	bool blocked;
	bool cancelled;

	uint32_t peer;
	uint32_t seq;

	ubus_data_handler_t raw_data_cb;
	ubus_data_handler_t data_cb;
	ubus_complete_handler_t complete_cb;

	struct ubus_context *ctx;
	void *priv;
};


struct ubus_context *ubus_connect(const char *path);
void ubus_free(struct ubus_context *ctx);

const char *ubus_strerror(int error);

static inline void ubus_add_uloop(struct ubus_context *ctx)
{
	uloop_fd_add(&ctx->sock, ULOOP_EDGE_TRIGGER | ULOOP_BLOCKING | ULOOP_READ);
}

/* ----------- raw request handling ----------- */

/* wait for a request to complete and return its status */
int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req);

/* complete a request asynchronously */
void ubus_complete_request_async(struct ubus_context *ctx,
				 struct ubus_request *req);

/* abort an asynchronous request */
void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req);

/* ----------- objects ----------- */

int ubus_lookup(struct ubus_context *ctx, const char *path,
		ubus_lookup_handler_t cb, void *priv);

int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id);

/* ----------- rpc ----------- */

/* invoke a method on a specific object */
int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
                struct blob_attr *msg, ubus_data_handler_t cb, void *priv);

/* asynchronous version of ubus_invoke() */
void ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
                       struct blob_attr *msg, struct ubus_request *req);

/* make an object visible to remote connections */
int ubus_publish(struct ubus_context *ctx, struct ubus_object *obj);

/* send a reply to an incoming object method call */
int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
		    struct blob_attr *msg);