2 * Copyright (C) 2011-2012 Felix Fietkau <nbd@openwrt.org>
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
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.
15 #include "libubus-internal.h"
17 void __hidden
ubus_process_invoke(struct ubus_context
*ctx
, struct ubus_msghdr
*hdr
)
19 struct blob_attr
**attrbuf
;
20 struct ubus_request_data req
= {};
21 struct ubus_object
*obj
;
27 attrbuf
= ubus_parse_msg(hdr
->data
);
29 if (!attrbuf
[UBUS_ATTR_OBJID
])
32 req
.object
= blob_get_u32(attrbuf
[UBUS_ATTR_OBJID
]);
34 if (!attrbuf
[UBUS_ATTR_METHOD
]) {
35 ret
= UBUS_STATUS_INVALID_ARGUMENT
;
39 obj
= avl_find_element(&ctx
->objects
, &req
.object
, obj
, avl
);
41 ret
= UBUS_STATUS_NOT_FOUND
;
45 for (method
= 0; method
< obj
->n_methods
; method
++)
46 if (!obj
->methods
[method
].name
||
47 !strcmp(obj
->methods
[method
].name
,
48 blob_data(attrbuf
[UBUS_ATTR_METHOD
])))
52 ret
= UBUS_STATUS_METHOD_NOT_FOUND
;
56 ret
= obj
->methods
[method
].handler(ctx
, obj
, &req
,
57 blob_data(attrbuf
[UBUS_ATTR_METHOD
]),
58 attrbuf
[UBUS_ATTR_DATA
]);
63 ubus_complete_deferred_request(ctx
, &req
, ret
);
66 static void ubus_add_object_cb(struct ubus_request
*req
, int type
, struct blob_attr
*msg
)
68 struct ubus_object
*obj
= req
->priv
;
69 struct blob_attr
**attrbuf
= ubus_parse_msg(msg
);
71 if (!attrbuf
[UBUS_ATTR_OBJID
])
74 obj
->id
= blob_get_u32(attrbuf
[UBUS_ATTR_OBJID
]);
76 if (attrbuf
[UBUS_ATTR_OBJTYPE
])
77 obj
->type
->id
= blob_get_u32(attrbuf
[UBUS_ATTR_OBJTYPE
]);
79 obj
->avl
.key
= &obj
->id
;
80 avl_insert(&req
->ctx
->objects
, &obj
->avl
);
83 static void ubus_push_method_data(const struct ubus_method
*m
)
88 mtbl
= blobmsg_open_table(&b
, m
->name
);
90 for (i
= 0; i
< m
->n_policy
; i
++)
91 blobmsg_add_u32(&b
, m
->policy
[i
].name
, m
->policy
[i
].type
);
93 blobmsg_close_table(&b
, mtbl
);
96 static bool ubus_push_object_type(const struct ubus_object_type
*type
)
101 s
= blob_nest_start(&b
, UBUS_ATTR_SIGNATURE
);
103 for (i
= 0; i
< type
->n_methods
; i
++)
104 ubus_push_method_data(&type
->methods
[i
]);
106 blob_nest_end(&b
, s
);
111 int ubus_add_object(struct ubus_context
*ctx
, struct ubus_object
*obj
)
113 struct ubus_request req
;
116 blob_buf_init(&b
, 0);
118 if (obj
->name
&& obj
->type
) {
119 blob_put_string(&b
, UBUS_ATTR_OBJPATH
, obj
->name
);
122 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
);
123 else if (!ubus_push_object_type(obj
->type
))
124 return UBUS_STATUS_INVALID_ARGUMENT
;
127 if (ubus_start_request(ctx
, &req
, b
.head
, UBUS_MSG_ADD_OBJECT
, 0) < 0)
128 return UBUS_STATUS_INVALID_ARGUMENT
;
130 req
.raw_data_cb
= ubus_add_object_cb
;
132 ret
= ubus_complete_request(ctx
, &req
, 0);
137 return UBUS_STATUS_NO_DATA
;
142 static void ubus_remove_object_cb(struct ubus_request
*req
, int type
, struct blob_attr
*msg
)
144 struct ubus_object
*obj
= req
->priv
;
145 struct blob_attr
**attrbuf
= ubus_parse_msg(msg
);
147 if (!attrbuf
[UBUS_ATTR_OBJID
])
152 if (attrbuf
[UBUS_ATTR_OBJTYPE
] && obj
->type
)
155 avl_delete(&req
->ctx
->objects
, &obj
->avl
);
158 int ubus_remove_object(struct ubus_context
*ctx
, struct ubus_object
*obj
)
160 struct ubus_request req
;
163 blob_buf_init(&b
, 0);
164 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
);
166 if (ubus_start_request(ctx
, &req
, b
.head
, UBUS_MSG_REMOVE_OBJECT
, 0) < 0)
167 return UBUS_STATUS_INVALID_ARGUMENT
;
169 req
.raw_data_cb
= ubus_remove_object_cb
;
171 ret
= ubus_complete_request(ctx
, &req
, 0);
176 return UBUS_STATUS_NO_DATA
;