2 * Copyright (C) 2015, 2016 "IoT.bzh"
3 * Author "Fulup Ar Foll"
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #define _GNU_SOURCE /* See feature_test_macros(7) */
22 #include <json-c/json.h>
24 #include <afb/afb-plugin.h>
26 #include "utils-jbus.h"
28 static const char _added_[] = "added";
29 static const char _auto_[] = "auto";
30 static const char _continue_[] = "continue";
31 static const char _changed_[] = "changed";
32 static const char _detail_[] = "detail";
33 static const char _id_[] = "id";
34 static const char _install_[] = "install";
35 static const char _local_[] = "local";
36 static const char _mode_[] = "mode";
37 static const char _remote_[] = "remote";
38 static const char _runid_[] = "runid";
39 static const char _runnables_[] = "runnables";
40 static const char _runners_[] = "runners";
41 static const char _start_[] = "start";
42 static const char _state_[] = "state";
43 static const char _stop_[] = "stop";
44 static const char _terminate_[] = "terminate";
45 static const char _uninstall_[] = "uninstall";
46 static const char _uri_[] = "uri";
48 static const struct AFB_interface *afb_interface;
50 static struct jbus *jbus;
54 struct afb_req request;
58 static struct memo *make_memo(struct afb_req request, const char *method)
60 struct memo *memo = malloc(sizeof *memo);
62 memo->request = request;
63 memo->method = method;
64 afb_req_addref(request);
69 static void application_list_changed(const char *data, void *closure)
71 afb_daemon_broadcast_event(afb_interface->daemon, "application-list-changed", NULL);
74 static struct json_object *embed(const char *tag, struct json_object *obj)
76 struct json_object *result;
83 result = json_object_new_object();
89 /* TODO why is json-c not returning a status? */
90 json_object_object_add(result, tag, obj);
96 static void embed_call_void_callback(int status, struct json_object *obj, struct memo *memo)
98 if (afb_interface->verbosity)
99 fprintf(stderr, "(afm-main-plugin) %s(true) -> %s\n", memo->method,
100 obj ? json_object_to_json_string(obj) : "NULL");
102 afb_req_fail(memo->request, "failed", "framework daemon failure");
104 obj = json_object_get(obj);
105 obj = embed(memo->method, obj);
107 afb_req_fail(memo->request, "failed", "framework daemon failure");
109 afb_req_success(memo->request, obj, NULL);
112 afb_req_unref(memo->request);
116 static void embed_call_void(struct afb_req request, const char *method)
118 struct memo *memo = make_memo(request, method);
120 afb_req_fail(request, "failed", "out of memory");
121 else if (jbus_call_sj(jbus, method, "true", (void*)embed_call_void_callback, memo) < 0) {
122 afb_req_fail(request, "failed", "dbus failure");
127 static void call_appid_callback(int status, struct json_object *obj, struct memo *memo)
129 if (afb_interface->verbosity)
130 fprintf(stderr, "(afm-main-plugin) %s -> %s\n", memo->method,
131 obj ? json_object_to_json_string(obj) : "NULL");
133 afb_req_fail(memo->request, "failed", "framework daemon failure");
135 obj = json_object_get(obj);
136 afb_req_success(memo->request, obj, NULL);
138 afb_req_unref(memo->request);
142 static void call_appid(struct afb_req request, const char *method)
146 const char *id = afb_req_value(request, _id_);
148 afb_req_fail(request, "bad-request", "missing 'id'");
151 memo = make_memo(request, method);
152 if (asprintf(&sid, "\"%s\"", id) <= 0 || memo == NULL) {
153 afb_req_fail(request, "server-error", "out of memory");
157 if (jbus_call_sj(jbus, method, sid, (void*)call_appid_callback, memo) < 0) {
158 afb_req_fail(request, "failed", "dbus failure");
164 static void call_runid(struct afb_req request, const char *method)
166 struct json_object *obj;
167 const char *id = afb_req_value(request, _runid_);
169 afb_req_fail(request, "bad-request", "missing 'runid'");
172 obj = jbus_call_sj_sync(jbus, method, id);
173 if (afb_interface->verbosity)
174 fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, id,
175 obj ? json_object_to_json_string(obj) : "NULL");
177 afb_req_fail(request, "failed", "framework daemon failure");
180 obj = json_object_get(obj);
181 afb_req_success(request, obj, NULL);
184 /************************** entries ******************************/
186 static void runnables(struct afb_req request)
188 embed_call_void(request, _runnables_);
191 static void detail(struct afb_req request)
193 call_appid(request, _detail_);
196 static void start(struct afb_req request)
198 struct json_object *obj;
199 const char *id, *mode;
204 id = afb_req_value(request, _id_);
206 afb_req_fail(request, "bad-request", "missing 'id'");
210 mode = afb_req_value(request, _mode_);
211 if (mode == NULL || !strcmp(mode, _auto_)) {
212 mode = afb_interface->mode == AFB_MODE_REMOTE ? _remote_ : _local_;
215 /* create the query */
216 rc = asprintf(&query, "{\"id\":\"%s\",\"mode\":\"%s\"}", id, mode);
218 afb_req_fail(request, "server-error", "out of memory");
222 /* calls the service */
223 obj = jbus_call_sj_sync(jbus, _start_, query);
224 if (afb_interface->verbosity)
225 fprintf(stderr, "(afm-main-plugin) start(%s) -> %s\n", query,
226 obj ? json_object_to_json_string(obj) : "NULL");
230 obj = json_object_get(obj);
232 afb_req_fail(request, "failed", "framework daemon failure");
236 /* embed if needed */
237 if (json_object_get_type(obj) == json_type_int)
238 obj = embed(_runid_, obj);
239 afb_req_success(request, obj, NULL);
242 static void terminate(struct afb_req request)
244 call_runid(request, _terminate_);
247 static void stop(struct afb_req request)
249 call_runid(request, _stop_);
252 static void continue_(struct afb_req request)
254 call_runid(request, _continue_);
257 static void runners(struct afb_req request)
259 embed_call_void(request, _runners_);
262 static void state(struct afb_req request)
264 call_runid(request, _state_);
267 static void install(struct afb_req request)
269 struct json_object *obj, *added;
271 const char *filename;
274 /* get the argument */
275 arg = afb_req_get(request, "widget");
277 if (filename == NULL) {
278 afb_req_fail(request, "bad-request", "missing 'widget' file");
282 /* makes the query */
283 if (0 >= asprintf(&query, "\"%s\"", filename)) {
284 afb_req_fail(request, "server-error", "out of memory");
288 obj = jbus_call_sj_sync(jbus, _install_, query);
289 if (afb_interface->verbosity)
290 fprintf(stderr, "(afm-main-plugin) install(%s) -> %s\n", query,
291 obj ? json_object_to_json_string(obj) : "NULL");
296 afb_req_fail(request, "failed", "framework daemon failure");
300 /* embed if needed */
301 if (json_object_object_get_ex(obj, _added_, &added))
303 obj = json_object_get(obj);
304 obj = embed(_id_, obj);
305 afb_req_success(request, obj, NULL);
308 static void uninstall(struct afb_req request)
310 call_appid(request, _uninstall_);
313 static const struct AFB_verb_desc_v1 verbs[] =
315 {_runnables_, AFB_SESSION_CHECK, runnables, "Get list of runnable applications"},
316 {_detail_ , AFB_SESSION_CHECK, detail, "Get the details for one application"},
317 {_start_ , AFB_SESSION_CHECK, start, "Start an application"},
318 {_terminate_, AFB_SESSION_CHECK, terminate, "Terminate a running application"},
319 {_stop_ , AFB_SESSION_CHECK, stop, "Stop (pause) a running application"},
320 {_continue_ , AFB_SESSION_CHECK, continue_, "Continue (resume) a stopped application"},
321 {_runners_ , AFB_SESSION_CHECK, runners, "Get the list of running applications"},
322 {_state_ , AFB_SESSION_CHECK, state, "Get the state of a running application"},
323 {_install_ , AFB_SESSION_CHECK, install, "Install an application using a widget file"},
324 {_uninstall_, AFB_SESSION_CHECK, uninstall, "Uninstall an application"},
325 { NULL, 0, NULL, NULL }
328 static const struct AFB_plugin plug_desc = {
329 .type = AFB_PLUGIN_VERSION_1,
331 .info = "Application Framework Master Service",
332 .prefix = "afm-main",
337 const struct AFB_plugin *pluginAfbV1Register(const struct AFB_interface *itf)
342 /* records the interface */
343 assert (afb_interface == NULL);
346 /* creates the jbus for accessing afm-user-daemon */
347 sbus = afb_daemon_get_user_bus(itf->daemon);
350 jbus = create_jbus(sbus, "/org/AGL/afm/user");
354 /* records the signal handler */
355 rc = jbus_on_signal_s(jbus, _changed_, application_list_changed, NULL);