4 static struct blob_buf b
;
5 static struct ubus_msg_buf
*retmsg
;
6 static int *retmsg_data
;
8 static struct blob_attr
*attrbuf
[UBUS_ATTR_MAX
];
10 typedef int (*ubus_cmd_cb
)(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
);
12 static const struct blob_attr_info ubus_policy
[UBUS_ATTR_MAX
] = {
13 [UBUS_ATTR_SIGNATURE
] = { .type
= BLOB_ATTR_NESTED
},
14 [UBUS_ATTR_OBJTYPE
] = { .type
= BLOB_ATTR_INT32
},
15 [UBUS_ATTR_OBJPATH
] = { .type
= BLOB_ATTR_STRING
},
16 [UBUS_ATTR_OBJID
] = { .type
= BLOB_ATTR_INT32
},
17 [UBUS_ATTR_STATUS
] = { .type
= BLOB_ATTR_INT32
},
20 struct blob_attr
**ubus_parse_msg(struct blob_attr
*msg
)
22 blob_parse(msg
, attrbuf
, ubus_policy
, UBUS_ATTR_MAX
);
26 static void ubus_msg_init(struct ubus_msg_buf
*ub
, uint8_t type
, uint16_t seq
, uint32_t peer
)
34 static struct ubus_msg_buf
*ubus_msg_from_blob(bool shared
)
36 return ubus_msg_new(b
.head
, blob_raw_len(b
.head
), shared
);
39 static struct ubus_msg_buf
*ubus_reply_from_blob(struct ubus_msg_buf
*ub
, bool shared
)
41 struct ubus_msg_buf
*new;
43 new = ubus_msg_new(b
.head
, blob_raw_len(b
.head
), shared
);
47 ubus_msg_init(new, UBUS_MSG_DATA
, ub
->hdr
.seq
, ub
->hdr
.peer
);
51 bool ubusd_send_hello(struct ubus_client
*cl
)
53 struct ubus_msg_buf
*ub
;
56 ub
= ubus_msg_from_blob(true);
60 ubus_msg_init(ub
, UBUS_MSG_HELLO
, 0, cl
->id
.id
);
61 ubus_msg_send(cl
, ub
, true);
65 static int ubusd_send_pong(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
67 ub
->hdr
.type
= UBUS_MSG_DATA
;
68 ubus_msg_send(cl
, ub
, false);
72 static int ubusd_handle_publish(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
74 struct ubus_object
*obj
;
76 obj
= ubusd_create_object(cl
, attr
);
78 return UBUS_STATUS_INVALID_ARGUMENT
;
81 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
82 if (attr
[UBUS_ATTR_SIGNATURE
])
83 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
85 ub
= ubus_reply_from_blob(ub
, true);
87 return UBUS_STATUS_NO_DATA
;
89 ubus_msg_send(cl
, ub
, true);
93 static void ubusd_send_obj(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct ubus_object
*obj
)
95 struct ubus_method
*m
;
101 blob_put_string(&b
, UBUS_ATTR_OBJPATH
, obj
->path
.key
);
102 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
103 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
105 s
= blob_nest_start(&b
, UBUS_ATTR_SIGNATURE
);
106 list_for_each_entry(m
, &obj
->type
->methods
, list
)
107 blob_put(&b
, blob_id(m
->data
), blob_data(m
->data
), blob_len(m
->data
));
108 blob_nest_end(&b
, s
);
110 ub
= ubus_reply_from_blob(ub
, true);
114 ubus_msg_send(cl
, ub
, true);
117 static int ubusd_handle_lookup(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
119 struct ubus_object
*obj
;
121 bool wildcard
= false;
125 if (!attr
[UBUS_ATTR_OBJPATH
]) {
126 avl_for_each_element(&path
, obj
, path
)
127 ubusd_send_obj(cl
, ub
, obj
);
131 objpath
= blob_data(attr
[UBUS_ATTR_OBJPATH
]);
132 len
= strlen(objpath
);
133 if (objpath
[len
- 1] != '*') {
134 obj
= avl_find_element(&path
, objpath
, obj
, path
);
136 return UBUS_STATUS_NOT_FOUND
;
138 ubusd_send_obj(cl
, ub
, obj
);
145 obj
= avl_find_ge_element(&path
, objpath
, obj
, path
);
147 return UBUS_STATUS_NOT_FOUND
;
149 while (!strncmp(objpath
, obj
->path
.key
, len
)) {
151 ubusd_send_obj(cl
, ub
, obj
);
152 if (obj
== avl_last_element(&path
, obj
, path
))
154 obj
= avl_next_element(obj
, path
);
158 return UBUS_STATUS_NOT_FOUND
;
163 static int ubusd_handle_invoke(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
165 struct ubus_object
*obj
= NULL
;
169 if (!attr
[UBUS_ATTR_METHOD
] || !attr
[UBUS_ATTR_OBJID
])
170 return UBUS_STATUS_INVALID_ARGUMENT
;
172 id
= ubus_find_id(&objects
, blob_get_int32(attr
[UBUS_ATTR_OBJID
]));
174 return UBUS_STATUS_NOT_FOUND
;
176 obj
= container_of(id
, struct ubus_object
, id
);
178 method
= blob_data(attr
[UBUS_ATTR_METHOD
]);
181 return obj
->recv_msg(cl
, method
, attr
[UBUS_ATTR_DATA
]);
183 blob_buf_init(&b
, 0);
184 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
185 blob_put_string(&b
, UBUS_ATTR_METHOD
, method
);
186 if (attr
[UBUS_ATTR_DATA
])
187 blob_put(&b
, UBUS_ATTR_DATA
, blob_data(attr
[UBUS_ATTR_DATA
]),
188 blob_len(attr
[UBUS_ATTR_DATA
]));
192 ub
= ubus_reply_from_blob(ub
, true);
194 return UBUS_STATUS_NO_DATA
;
196 ub
->hdr
.type
= UBUS_MSG_INVOKE
;
197 ub
->hdr
.peer
= cl
->id
.id
;
198 ubus_msg_send(obj
->client
, ub
, true);
203 static int ubusd_handle_response(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
205 struct ubus_object
*obj
;
207 if (!attr
[UBUS_ATTR_OBJID
] ||
208 (ub
->hdr
.type
== UBUS_MSG_STATUS
&& !attr
[UBUS_ATTR_STATUS
]) ||
209 (ub
->hdr
.type
== UBUS_MSG_DATA
&& !attr
[UBUS_ATTR_DATA
]))
212 obj
= ubusd_find_object(blob_get_int32(attr
[UBUS_ATTR_OBJID
]));
216 if (cl
!= obj
->client
)
219 cl
= ubusd_get_client_by_id(ub
->hdr
.peer
);
223 ub
->hdr
.peer
= blob_get_int32(attr
[UBUS_ATTR_OBJID
]);
224 ubus_msg_send(cl
, ub
, true);
232 static const ubus_cmd_cb handlers
[__UBUS_MSG_LAST
] = {
233 [UBUS_MSG_PING
] = ubusd_send_pong
,
234 [UBUS_MSG_PUBLISH
] = ubusd_handle_publish
,
235 [UBUS_MSG_LOOKUP
] = ubusd_handle_lookup
,
236 [UBUS_MSG_INVOKE
] = ubusd_handle_invoke
,
237 [UBUS_MSG_STATUS
] = ubusd_handle_response
,
238 [UBUS_MSG_DATA
] = ubusd_handle_response
,
241 void ubusd_receive_message(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
)
243 ubus_cmd_cb cb
= NULL
;
246 retmsg
->hdr
.seq
= ub
->hdr
.seq
;
247 retmsg
->hdr
.peer
= ub
->hdr
.peer
;
249 if (ub
->hdr
.type
< __UBUS_MSG_LAST
)
250 cb
= handlers
[ub
->hdr
.type
];
253 ret
= cb(cl
, ub
, ubus_parse_msg(ub
->data
));
255 ret
= UBUS_STATUS_INVALID_COMMAND
;
262 *retmsg_data
= htonl(ret
);
263 ubus_msg_send(cl
, retmsg
, false);
266 static void __init
ubusd_proto_init(void)
268 blob_buf_init(&b
, 0);
269 blob_put_int32(&b
, UBUS_ATTR_STATUS
, 0);
271 retmsg
= ubus_msg_from_blob(false);
275 retmsg
->hdr
.type
= UBUS_MSG_STATUS
;
276 retmsg_data
= blob_data(blob_data(retmsg
->data
));