1 #include <libubox/avl-cmp.h>
6 struct avl_tree services
;
7 static struct blob_buf b
;
10 service_instance_add(struct service
*s
, struct blob_attr
*attr
)
12 struct service_instance
*in
;
14 if (blobmsg_type(attr
) != BLOBMSG_TYPE_TABLE
)
17 in
= calloc(1, sizeof(*in
));
21 instance_init(in
, s
, attr
);
22 vlist_add(&s
->instances
, &in
->node
, (void *) in
->name
);
26 service_instance_update(struct vlist_tree
*tree
, struct vlist_node
*node_new
,
27 struct vlist_node
*node_old
)
29 struct service_instance
*in_o
= NULL
, *in_n
= NULL
;
32 in_o
= container_of(node_old
, struct service_instance
, node
);
35 in_n
= container_of(node_new
, struct service_instance
, node
);
38 DPRINTF("Update instance %s::%s\n", in_o
->srv
->name
, in_o
->name
);
39 instance_update(in_o
, in_n
);
42 DPRINTF("Free instance %s::%s\n", in_o
->srv
->name
, in_o
->name
);
43 instance_stop(in_o
, false);
46 DPRINTF("Create instance %s::%s\n", in_n
->srv
->name
, in_n
->name
);
51 static struct service
*
52 service_alloc(const char *name
)
57 s
= calloc(1, sizeof(*s
) + strlen(name
) + 1);
59 new_name
= (char *) (s
+ 1);
60 strcpy(new_name
, name
);
62 vlist_init(&s
->instances
, avl_strcmp
, service_instance_update
);
63 s
->instances
.keep_old
= true;
73 SERVICE_SET_INSTANCES
,
77 static const struct blobmsg_policy service_set_attrs
[__SERVICE_SET_MAX
] = {
78 [SERVICE_SET_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
79 [SERVICE_SET_SCRIPT
] = { "script", BLOBMSG_TYPE_STRING
},
80 [SERVICE_SET_INSTANCES
] = { "instances", BLOBMSG_TYPE_TABLE
},
85 service_update(struct service
*s
, struct blob_attr
*config
, struct blob_attr
**tb
, bool add
)
87 struct blob_attr
*cur
;
90 if (tb
[SERVICE_SET_INSTANCES
]) {
92 vlist_update(&s
->instances
);
93 blobmsg_for_each_attr(cur
, tb
[SERVICE_SET_INSTANCES
], rem
) {
94 service_instance_add(s
, cur
);
97 vlist_flush(&s
->instances
);
104 service_delete(struct service
*s
)
106 vlist_flush_all(&s
->instances
);
107 avl_delete(&services
, &s
->avl
);
117 static const struct blobmsg_policy service_attrs
[__SERVICE_ATTR_MAX
] = {
118 [SERVICE_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
122 SERVICE_DEL_ATTR_NAME
,
123 SERVICE_DEL_ATTR_INSTANCE
,
124 __SERVICE_DEL_ATTR_MAX
,
127 static const struct blobmsg_policy service_del_attrs
[__SERVICE_DEL_ATTR_MAX
] = {
128 [SERVICE_DEL_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
129 [SERVICE_DEL_ATTR_INSTANCE
] = { "instance", BLOBMSG_TYPE_STRING
},
134 service_handle_set(struct ubus_context
*ctx
, struct ubus_object
*obj
,
135 struct ubus_request_data
*req
, const char *method
,
136 struct blob_attr
*msg
)
138 struct blob_attr
*tb
[__SERVICE_SET_MAX
], *cur
;
139 struct service
*s
= NULL
;
141 int ret
= UBUS_STATUS_INVALID_ARGUMENT
;
142 bool add
= !strcmp(method
, "add");
144 blobmsg_parse(service_set_attrs
, __SERVICE_SET_MAX
, tb
, blob_data(msg
), blob_len(msg
));
145 cur
= tb
[SERVICE_ATTR_NAME
];
149 name
= blobmsg_data(cur
);
151 s
= avl_find_element(&services
, name
, s
, avl
);
153 DPRINTF("Update service %s\n", name
);
154 return service_update(s
, msg
, tb
, add
);
157 DPRINTF("Create service %s\n", name
);
158 s
= service_alloc(name
);
160 return UBUS_STATUS_UNKNOWN_ERROR
;
162 ret
= service_update(s
, msg
, tb
, add
);
166 avl_insert(&services
, &s
->avl
);
176 service_dump(struct service
*s
)
178 struct service_instance
*in
;
181 c
= blobmsg_open_table(&b
, s
->name
);
182 i
= blobmsg_open_table(&b
, "instances");
183 vlist_for_each_element(&s
->instances
, in
, node
)
184 instance_dump(&b
, in
);
185 blobmsg_close_table(&b
, i
);
186 blobmsg_close_table(&b
, c
);
190 service_handle_list(struct ubus_context
*ctx
, struct ubus_object
*obj
,
191 struct ubus_request_data
*req
, const char *method
,
192 struct blob_attr
*msg
)
196 blob_buf_init(&b
, 0);
197 avl_for_each_element(&services
, s
, avl
)
200 ubus_send_reply(ctx
, req
, b
.head
);
206 service_handle_delete(struct ubus_context
*ctx
, struct ubus_object
*obj
,
207 struct ubus_request_data
*req
, const char *method
,
208 struct blob_attr
*msg
)
210 struct blob_attr
*tb
[__SERVICE_DEL_ATTR_MAX
], *cur
;
211 struct service
*s
, *tmp
;
212 struct service_instance
*in
;
214 blobmsg_parse(service_del_attrs
, __SERVICE_DEL_ATTR_MAX
, tb
, blob_data(msg
), blob_len(msg
));
216 cur
= tb
[SERVICE_DEL_ATTR_NAME
];
218 avl_for_each_element_safe(&services
, s
, avl
, tmp
)
223 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
225 return UBUS_STATUS_NOT_FOUND
;
227 cur
= tb
[SERVICE_DEL_ATTR_INSTANCE
];
233 in
= vlist_find(&s
->instances
, blobmsg_data(cur
), in
, node
);
235 fprintf(stderr
, "instance %s not found\n", (char *) blobmsg_data(cur
));
236 return UBUS_STATUS_NOT_FOUND
;
239 vlist_delete(&s
->instances
, &in
->node
);
245 service_handle_update(struct ubus_context
*ctx
, struct ubus_object
*obj
,
246 struct ubus_request_data
*req
, const char *method
,
247 struct blob_attr
*msg
)
249 struct blob_attr
*tb
[__SERVICE_ATTR_MAX
], *cur
;
252 blobmsg_parse(service_attrs
, __SERVICE_ATTR_MAX
, tb
, blob_data(msg
), blob_len(msg
));
254 cur
= tb
[SERVICE_ATTR_NAME
];
256 return UBUS_STATUS_INVALID_ARGUMENT
;
258 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
260 return UBUS_STATUS_NOT_FOUND
;
262 if (!strcmp(method
, "update_start"))
263 vlist_update(&s
->instances
);
265 vlist_flush(&s
->instances
);
270 static struct ubus_method main_object_methods
[] = {
271 UBUS_METHOD("set", service_handle_set
, service_set_attrs
),
272 UBUS_METHOD("add", service_handle_set
, service_set_attrs
),
273 UBUS_METHOD("list", service_handle_list
, service_attrs
),
274 UBUS_METHOD("delete", service_handle_delete
, service_del_attrs
),
275 UBUS_METHOD("update_start", service_handle_update
, service_attrs
),
276 UBUS_METHOD("update_complete", service_handle_update
, service_attrs
),
279 static struct ubus_object_type main_object_type
=
280 UBUS_OBJECT_TYPE("service", main_object_methods
);
282 static struct ubus_object main_object
= {
284 .type
= &main_object_type
,
285 .methods
= main_object_methods
,
286 .n_methods
= ARRAY_SIZE(main_object_methods
),
289 void procd_init_service(struct ubus_context
*ctx
)
291 avl_init(&services
, avl_strcmp
, false, NULL
);
292 ubus_add_object(ctx
, &main_object
);