4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
28 #include "utils-jbus.h"
29 #include "utils-json.h"
32 #include "afm-launch-mode.h"
35 static const char appname[] = "afm-user-daemon";
40 "usage: %s [-q] [-v] [-r rootdir]... [-a appdir]...\n"
42 " -a appdir adds an application directory\n"
43 " -r rootdir adds a root directory of applications\n"
44 " -d run as a daemon\n"
52 static struct option options[] = {
53 { "root", required_argument, NULL, 'r' },
54 { "application", required_argument, NULL, 'a' },
55 { "daemon", no_argument, NULL, 'd' },
56 { "quiet", no_argument, NULL, 'q' },
57 { "verbose", no_argument, NULL, 'v' },
58 { "help", no_argument, NULL, 'h' },
62 static struct jbus *jbuses[2];
63 static struct afm_db *afdb;
65 const char error_nothing[] = "[]";
66 const char error_bad_request[] = "\"bad request\"";
67 const char error_not_found[] = "\"not found\"";
68 const char error_cant_start[] = "\"can't start\"";
69 const char error_system[] = "\"system error\"";
71 static const char *getappid(struct json_object *obj)
73 return json_type_string == json_object_get_type(obj) ? json_object_get_string(obj) : NULL;
76 static int getrunid(struct json_object *obj)
78 return json_type_int == json_object_get_type(obj) ? json_object_get_int(obj) : 0;
81 static void reply(struct jreq *jreq, struct json_object *resp, const char *errstr)
84 jbus_reply_j(jreq, resp);
86 jbus_reply_error_s(jreq, errstr);
89 static void reply_status(struct jreq *jreq, int status)
92 jbus_reply_error_s(jreq, error_not_found);
94 jbus_reply_s(jreq, "true");
97 static void on_runnables(struct jreq *jreq, struct json_object *obj)
99 struct json_object *resp;
100 INFO("method runnables called");
101 resp = afm_db_application_list(afdb);
102 jbus_reply_j(jreq, resp);
103 json_object_put(resp);
106 static void on_detail(struct jreq *jreq, struct json_object *obj)
109 struct json_object *resp;
110 appid = getappid(obj);
111 INFO("method detail called for %s", appid);
112 resp = afm_db_get_application_public(afdb, appid);
113 reply(jreq, resp, error_not_found);
114 json_object_put(resp);
117 static void on_start(struct jreq *jreq, struct json_object *obj)
119 const char *appid, *modestr;
121 struct json_object *appli, *resp;
124 enum afm_launch_mode mode;
126 /* get the parameters */
127 mode = invalid_launch_mode;
128 if (j_read_string(obj, &appid)) {
129 mode = default_launch_mode;
130 } else if (j_read_string_at(obj, "id", &appid)) {
131 if (j_read_string_at(obj, "mode", &modestr)) {
132 mode = launch_mode_of_string(modestr);
134 mode = default_launch_mode;
137 if (!launch_mode_is_valid(mode)) {
138 jbus_reply_error_s(jreq, error_bad_request);
142 /* get the application */
143 INFO("method start called for %s mode=%s", appid, mode);
144 appli = afm_db_get_application(afdb, appid);
146 jbus_reply_error_s(jreq, error_not_found);
150 /* launch the application */
152 runid = afm_run_start(appli, mode, &uri);
154 jbus_reply_error_s(jreq, error_cant_start);
160 /* returns only the runid */
161 snprintf(runidstr, sizeof runidstr, "%d", runid);
162 runidstr[sizeof runidstr - 1] = 0;
163 jbus_reply_s(jreq, runidstr);
167 /* returns the runid and its uri */
168 resp = json_object_new_object();
169 if (resp != NULL && j_add_integer(resp, "runid", runid) && j_add_string(resp, "uri", uri))
170 jbus_reply_j(jreq, resp);
173 jbus_reply_error_s(jreq, error_cant_start);
175 json_object_put(resp);
179 static void on_stop(struct jreq *jreq, struct json_object *obj)
182 runid = getrunid(obj);
183 INFO("method stop called for %d", runid);
184 status = afm_run_stop(runid);
185 reply_status(jreq, status);
188 static void on_continue(struct jreq *jreq, struct json_object *obj)
191 runid = getrunid(obj);
192 INFO("method continue called for %d", runid);
193 status = afm_run_continue(runid);
194 reply_status(jreq, status);
197 static void on_terminate(struct jreq *jreq, struct json_object *obj)
200 runid = getrunid(obj);
201 INFO("method terminate called for %d", runid);
202 status = afm_run_terminate(runid);
203 reply_status(jreq, status);
206 static void on_runners(struct jreq *jreq, struct json_object *obj)
208 struct json_object *resp;
209 INFO("method runners called");
210 resp = afm_run_list();
211 jbus_reply_j(jreq, resp);
212 json_object_put(resp);
215 static void on_state(struct jreq *jreq, struct json_object *obj)
218 struct json_object *resp;
219 runid = getrunid(obj);
220 INFO("method state called for %d", runid);
221 resp = afm_run_state(runid);
222 reply(jreq, resp, error_not_found);
223 json_object_put(resp);
226 static void propagate(struct jreq *jreq, const char *msg, const char *method)
229 INFO("method %s propagated with %s", method, msg);
230 reply = jbus_call_ss_sync(jbuses[0], method, msg);
232 jbus_reply_s(jreq, reply);
236 jbus_reply_error_s(jreq, error_system);
239 static void on_install(struct jreq *jreq, const char *msg)
241 return propagate(jreq, msg, "install");
244 static void on_uninstall(struct jreq *jreq, const char *msg)
246 return propagate(jreq, msg, "uninstall");
249 static void on_signal_changed(struct json_object *obj)
251 /* update the database */
252 afm_db_update_applications(afdb);
253 /* re-propagate now */
254 jbus_send_signal_j(jbuses[1], "changed", obj);
257 static int daemonize()
267 int main(int ac, char **av)
273 /* first interpretation of arguments */
274 while ((i = getopt_long(ac, av, "hdqvr:a:", options, NULL)) >= 0) {
294 ERROR("missing argument value");
297 ERROR("unrecognized option");
302 /* init random generator */
303 srandom((unsigned int)time(NULL));
306 if (afm_run_init()) {
307 ERROR("afm_run_init failed");
312 afdb = afm_db_create();
314 ERROR("afm_create failed");
317 if (afm_db_add_root(afdb, FWK_APP_DIR)) {
318 ERROR("can't add root %s", FWK_APP_DIR);
322 /* second interpretation of arguments */
324 while ((i = getopt_long(ac, av, "hdqvr:a:", options, NULL)) >= 0) {
327 if (afm_db_add_root(afdb, optarg)) {
328 ERROR("can't add root %s", optarg);
333 if (afm_db_add_application(afdb, optarg)) {
334 ERROR("can't add application %s", optarg);
341 /* update the database */
342 if (afm_db_update_applications(afdb)) {
343 ERROR("afm_update_applications failed");
347 if (daemon && daemonize()) {
348 ERROR("daemonization failed");
353 jbuses[0] = create_jbus(0, AFM_SYSTEM_DBUS_PATH);
355 ERROR("create_jbus failed for system");
358 if(jbus_on_signal_j(jbuses[0], "changed", on_signal_changed)) {
359 ERROR("adding signal observer failed");
364 jbuses[1] = create_jbus(1, AFM_USER_DBUS_PATH);
366 ERROR("create_jbus failed");
369 if(jbus_add_service_j(jbuses[1], "runnables", on_runnables)
370 || jbus_add_service_j(jbuses[1], "detail", on_detail)
371 || jbus_add_service_j(jbuses[1], "start", on_start)
372 || jbus_add_service_j(jbuses[1], "terminate", on_terminate)
373 || jbus_add_service_j(jbuses[1], "stop", on_stop)
374 || jbus_add_service_j(jbuses[1], "continue", on_continue)
375 || jbus_add_service_j(jbuses[1], "runners", on_runners)
376 || jbus_add_service_j(jbuses[1], "state", on_state)
377 || jbus_add_service_s(jbuses[1], "install", on_install)
378 || jbus_add_service_s(jbuses[1], "uninstall", on_uninstall)) {
379 ERROR("adding services failed");
384 if (jbus_start_serving(jbuses[1])) {
385 ERROR("can't start server");
388 while (jbus_read_write_dispatch_multiple(jbuses, 2, -1, 20) >= 0);