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
;
13 const char *name
= blobmsg_name(attr
);
15 if (blobmsg_type(attr
) != BLOBMSG_TYPE_TABLE
)
18 in
= calloc(1, sizeof(*in
));
22 instance_init(in
, attr
);
23 vlist_add(&s
->instances
, &in
->node
, (void *) name
);
27 service_instance_update(struct vlist_tree
*tree
, struct vlist_node
*node_new
,
28 struct vlist_node
*node_old
)
30 struct service_instance
*in_o
= NULL
, *in_n
= NULL
;
33 in_o
= container_of(node_old
, struct service_instance
, node
);
36 in_n
= container_of(node_new
, struct service_instance
, node
);
39 instance_update(in_o
, in_n
);
42 instance_stop(in_o
, false);
49 static struct service
*
50 service_alloc(const char *name
)
54 s
= calloc(1, sizeof(*s
));
55 vlist_init(&s
->instances
, avl_strcmp
, service_instance_update
);
56 s
->instances
.keep_old
= true;
64 SERVICE_ATTR_INSTANCES
,
68 static const struct blobmsg_policy service_attrs
[__SERVICE_ATTR_MAX
] = {
69 [SERVICE_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
70 [SERVICE_ATTR_SCRIPT
] = { "script", BLOBMSG_TYPE_STRING
},
71 [SERVICE_ATTR_INSTANCES
] = { "instances", BLOBMSG_TYPE_TABLE
},
76 service_update(struct service
*s
, struct blob_attr
*config
, struct blob_attr
**tb
)
78 struct blob_attr
*old_config
= s
->config
;
79 struct blob_attr
*cur
;
82 /* only the pointer changes, the content stays the same,
83 * no avl update necessary */
84 s
->name
= s
->avl
.key
= blobmsg_data(tb
[SERVICE_ATTR_NAME
]);
87 if (tb
[SERVICE_ATTR_INSTANCES
]) {
88 vlist_update(&s
->instances
);
89 blobmsg_for_each_attr(cur
, tb
[SERVICE_ATTR_INSTANCES
], rem
) {
90 service_instance_add(s
, cur
);
92 vlist_flush(&s
->instances
);
101 service_delete(struct service
*s
)
103 vlist_flush_all(&s
->instances
);
104 avl_delete(&services
, &s
->avl
);
110 service_handle_set(struct ubus_context
*ctx
, struct ubus_object
*obj
,
111 struct ubus_request_data
*req
, const char *method
,
112 struct blob_attr
*msg
)
114 struct blob_attr
*tb
[__SERVICE_ATTR_MAX
], *cur
;
115 struct service
*s
= NULL
;
117 int ret
= UBUS_STATUS_INVALID_ARGUMENT
;
119 msg
= blob_memdup(msg
);
121 return UBUS_STATUS_UNKNOWN_ERROR
;
123 blobmsg_parse(service_attrs
, __SERVICE_ATTR_MAX
, tb
, blob_data(msg
), blob_len(msg
));
124 cur
= tb
[SERVICE_ATTR_NAME
];
128 name
= blobmsg_data(cur
);
130 s
= avl_find_element(&services
, name
, s
, avl
);
132 return service_update(s
, msg
, tb
);
134 s
= service_alloc(name
);
136 return UBUS_STATUS_UNKNOWN_ERROR
;
138 ret
= service_update(s
, msg
, tb
);
142 avl_insert(&services
, &s
->avl
);
152 service_handle_list(struct ubus_context
*ctx
, struct ubus_object
*obj
,
153 struct ubus_request_data
*req
, const char *method
,
154 struct blob_attr
*msg
)
158 blob_buf_init(&b
, 0);
159 avl_for_each_element(&services
, s
, avl
) {
162 c
= blobmsg_open_table(&b
, s
->name
);
163 blobmsg_close_table(&b
, c
);
166 ubus_send_reply(ctx
, req
, b
.head
);
176 static const struct blobmsg_policy service_del_attrs
[__SERVICE_DEL_MAX
] = {
177 [SERVICE_DEL_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
182 service_handle_delete(struct ubus_context
*ctx
, struct ubus_object
*obj
,
183 struct ubus_request_data
*req
, const char *method
,
184 struct blob_attr
*msg
)
186 struct blob_attr
*tb
[__SERVICE_DEL_MAX
], *cur
;
187 struct service
*s
, *tmp
;
189 blobmsg_parse(service_del_attrs
, __SERVICE_DEL_MAX
, tb
, blob_data(msg
), blob_len(msg
));
191 cur
= tb
[SERVICE_ATTR_NAME
];
193 avl_for_each_element_safe(&services
, s
, avl
, tmp
)
198 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
200 return UBUS_STATUS_NOT_FOUND
;
206 static struct ubus_method main_object_methods
[] = {
207 { .name
= "list", .handler
= service_handle_list
},
208 { .name
= "set", .handler
= service_handle_set
},
209 { .name
= "delete", .handler
= service_handle_delete
},
212 static struct ubus_object_type main_object_type
=
213 UBUS_OBJECT_TYPE("service", main_object_methods
);
215 static struct ubus_object main_object
= {
217 .type
= &main_object_type
,
218 .methods
= main_object_methods
,
219 .n_methods
= ARRAY_SIZE(main_object_methods
),
222 void procd_init_service(struct ubus_context
*ctx
)
224 avl_init(&services
, avl_strcmp
, false, NULL
);
225 ubus_add_object(ctx
, &main_object
);