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] [-m mode] [-r rootdir]... [-a appdir]...\n"
42 " -a appdir adds an application directory\n"
43 " -r rootdir adds a root directory of applications\n"
44 " -m mode set default launch mode (local or remote)\n"
45 " -d run as a daemon\n"
53 static struct option options[] = {
54 { "root", required_argument, NULL, 'r' },
55 { "application", required_argument, NULL, 'a' },
56 { "mode", required_argument, NULL, 'm' },
57 { "daemon", no_argument, NULL, 'd' },
58 { "quiet", no_argument, NULL, 'q' },
59 { "verbose", no_argument, NULL, 'v' },
60 { "help", no_argument, NULL, 'h' },
64 static struct jbus *jbuses[2];
65 static struct afm_db *afdb;
67 const char error_nothing[] = "[]";
68 const char error_bad_request[] = "\"bad request\"";
69 const char error_not_found[] = "\"not found\"";
70 const char error_cant_start[] = "\"can't start\"";
71 const char error_system[] = "\"system error\"";
73 static const char *getappid(struct json_object *obj)
75 return json_type_string == json_object_get_type(obj) ? json_object_get_string(obj) : NULL;
78 static int getrunid(struct json_object *obj)
80 return json_type_int == json_object_get_type(obj) ? json_object_get_int(obj) : 0;
83 static void reply(struct jreq *jreq, struct json_object *resp, const char *errstr)
86 jbus_reply_j(jreq, resp);
88 jbus_reply_error_s(jreq, errstr);
91 static void reply_status(struct jreq *jreq, int status)
94 jbus_reply_error_s(jreq, error_not_found);
96 jbus_reply_s(jreq, "true");
99 static void on_runnables(struct jreq *jreq, struct json_object *obj)
101 struct json_object *resp;
102 INFO("method runnables called");
103 resp = afm_db_application_list(afdb);
104 jbus_reply_j(jreq, resp);
105 json_object_put(resp);
108 static void on_detail(struct jreq *jreq, struct json_object *obj)
111 struct json_object *resp;
112 appid = getappid(obj);
113 INFO("method detail called for %s", appid);
114 resp = afm_db_get_application_public(afdb, appid);
115 reply(jreq, resp, error_not_found);
116 json_object_put(resp);
119 static void on_start(struct jreq *jreq, struct json_object *obj)
121 const char *appid, *modestr;
123 struct json_object *appli, *resp;
126 enum afm_launch_mode mode;
128 /* get the parameters */
129 mode = invalid_launch_mode;
130 if (j_read_string(obj, &appid)) {
131 mode = get_default_launch_mode();
132 } else if (j_read_string_at(obj, "id", &appid)) {
133 if (j_read_string_at(obj, "mode", &modestr)) {
134 mode = launch_mode_of_name(modestr);
136 mode = get_default_launch_mode();
139 if (!is_valid_launch_mode(mode)) {
140 jbus_reply_error_s(jreq, error_bad_request);
144 /* get the application */
145 INFO("method start called for %s mode=%s", appid, name_of_launch_mode(mode));
146 appli = afm_db_get_application(afdb, appid);
148 jbus_reply_error_s(jreq, error_not_found);
152 /* launch the application */
154 runid = afm_run_start(appli, mode, &uri);
156 jbus_reply_error_s(jreq, error_cant_start);
162 /* returns only the runid */
163 snprintf(runidstr, sizeof runidstr, "%d", runid);
164 runidstr[sizeof runidstr - 1] = 0;
165 jbus_reply_s(jreq, runidstr);
169 /* returns the runid and its uri */
170 resp = json_object_new_object();
171 if (resp != NULL && j_add_integer(resp, "runid", runid) && j_add_string(resp, "uri", uri))
172 jbus_reply_j(jreq, resp);
175 jbus_reply_error_s(jreq, error_cant_start);
177 json_object_put(resp);
181 static void on_stop(struct jreq *jreq, struct json_object *obj)
184 runid = getrunid(obj);
185 INFO("method stop called for %d", runid);
186 status = afm_run_stop(runid);
187 reply_status(jreq, status);
190 static void on_continue(struct jreq *jreq, struct json_object *obj)
193 runid = getrunid(obj);
194 INFO("method continue called for %d", runid);
195 status = afm_run_continue(runid);
196 reply_status(jreq, status);
199 static void on_terminate(struct jreq *jreq, struct json_object *obj)
202 runid = getrunid(obj);
203 INFO("method terminate called for %d", runid);
204 status = afm_run_terminate(runid);
205 reply_status(jreq, status);
208 static void on_runners(struct jreq *jreq, struct json_object *obj)
210 struct json_object *resp;
211 INFO("method runners called");
212 resp = afm_run_list();
213 jbus_reply_j(jreq, resp);
214 json_object_put(resp);
217 static void on_state(struct jreq *jreq, struct json_object *obj)
220 struct json_object *resp;
221 runid = getrunid(obj);
222 INFO("method state called for %d", runid);
223 resp = afm_run_state(runid);
224 reply(jreq, resp, error_not_found);
225 json_object_put(resp);
228 static void propagate(struct jreq *jreq, const char *msg, const char *method)
231 INFO("method %s propagated with %s", method, msg);
232 reply = jbus_call_ss_sync(jbuses[0], method, msg);
234 jbus_reply_s(jreq, reply);
238 jbus_reply_error_s(jreq, error_system);
241 static void on_install(struct jreq *jreq, const char *msg)
243 return propagate(jreq, msg, "install");
246 static void on_uninstall(struct jreq *jreq, const char *msg)
248 return propagate(jreq, msg, "uninstall");
251 static void on_signal_changed(struct json_object *obj)
253 /* update the database */
254 afm_db_update_applications(afdb);
255 /* re-propagate now */
256 jbus_send_signal_j(jbuses[1], "changed", obj);
259 static int daemonize()
269 int main(int ac, char **av)
272 enum afm_launch_mode mode;
276 /* first interpretation of arguments */
277 while ((i = getopt_long(ac, av, "hdqvr:a:m:", options, NULL)) >= 0) {
297 mode = launch_mode_of_name(optarg);
298 if (!is_valid_launch_mode(mode)) {
299 ERROR("invalid mode '%s'", optarg);
302 set_default_launch_mode(mode);
305 ERROR("missing argument value");
308 ERROR("unrecognized option");
313 /* init random generator */
314 srandom((unsigned int)time(NULL));
317 if (afm_run_init()) {
318 ERROR("afm_run_init failed");
323 afdb = afm_db_create();
325 ERROR("afm_create failed");
328 if (afm_db_add_root(afdb, FWK_APP_DIR)) {
329 ERROR("can't add root %s", FWK_APP_DIR);
333 /* second interpretation of arguments */
335 while ((i = getopt_long(ac, av, "hdqvr:a:m:", options, NULL)) >= 0) {
338 if (afm_db_add_root(afdb, optarg)) {
339 ERROR("can't add root %s", optarg);
344 if (afm_db_add_application(afdb, optarg)) {
345 ERROR("can't add application %s", optarg);
352 /* update the database */
353 if (afm_db_update_applications(afdb)) {
354 ERROR("afm_update_applications failed");
358 if (daemon && daemonize()) {
359 ERROR("daemonization failed");
364 jbuses[0] = create_jbus_system(AFM_SYSTEM_DBUS_PATH);
366 ERROR("create_jbus failed for system");
369 if(jbus_on_signal_j(jbuses[0], "changed", on_signal_changed)) {
370 ERROR("adding signal observer failed");
375 jbuses[1] = create_jbus_session(AFM_USER_DBUS_PATH);
377 ERROR("create_jbus failed");
380 if(jbus_add_service_j(jbuses[1], "runnables", on_runnables)
381 || jbus_add_service_j(jbuses[1], "detail", on_detail)
382 || jbus_add_service_j(jbuses[1], "start", on_start)
383 || jbus_add_service_j(jbuses[1], "terminate", on_terminate)
384 || jbus_add_service_j(jbuses[1], "stop", on_stop)
385 || jbus_add_service_j(jbuses[1], "continue", on_continue)
386 || jbus_add_service_j(jbuses[1], "runners", on_runners)
387 || jbus_add_service_j(jbuses[1], "state", on_state)
388 || jbus_add_service_s(jbuses[1], "install", on_install)
389 || jbus_add_service_s(jbuses[1], "uninstall", on_uninstall)) {
390 ERROR("adding services failed");
395 if (jbus_start_serving(jbuses[1])) {
396 ERROR("can't start server");
399 while (jbus_read_write_dispatch_multiple(jbuses, 2, -1, 20) >= 0);