2 * Copyright (C) 2015 "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) */
24 #include "afb-plugin.h"
26 #include "utils-sbus.h"
27 #include "utils-jbus.h"
29 static const char _added_[] = "added";
30 static const char _auto_[] = "auto";
31 static const char _continue_[] = "continue";
32 static const char _changed_[] = "changed";
33 static const char _detail_[] = "detail";
34 static const char _id_[] = "id";
35 static const char _install_[] = "install";
36 static const char _local_[] = "local";
37 static const char _mode_[] = "mode";
38 static const char _remote_[] = "remote";
39 static const char _runid_[] = "runid";
40 static const char _runnables_[] = "runnables";
41 static const char _runners_[] = "runners";
42 static const char _start_[] = "start";
43 static const char _state_[] = "state";
44 static const char _stop_[] = "stop";
45 static const char _terminate_[] = "terminate";
46 static const char _uninstall_[] = "uninstall";
47 static const char _uri_[] = "uri";
49 static const struct AFB_interface *interface;
50 static struct afb_evmgr evmgr;
52 static struct jbus *jbus;
56 struct afb_req request;
60 static struct memo *make_memo(struct afb_req request, const char *method)
62 struct memo *memo = malloc(sizeof *memo);
64 memo->request = request;
65 memo->method = method;
70 static void application_list_changed(const char *data, void *closure)
72 afb_evmgr_push(evmgr, "application-list-changed", NULL);
75 static struct json_object *embed(const char *tag, struct json_object *obj)
77 struct json_object *result;
84 result = json_object_new_object();
90 /* TODO why is json-c not returning a status? */
91 json_object_object_add(result, tag, obj);
97 static void embed_call_void_callback(int status, struct json_object *obj, struct memo *memo)
99 if (interface->verbosity)
100 fprintf(stderr, "(afm-main-plugin) %s(true) -> %s\n", memo->method,
101 obj ? json_object_to_json_string(obj) : "NULL");
103 afb_req_fail(memo->request, "failed", "framework daemon failure");
105 obj = json_object_get(obj);
106 obj = embed(memo->method, obj);
108 afb_req_fail(memo->request, "failed", "framework daemon failure");
110 afb_req_success(memo->request, obj, NULL);
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 (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);
141 static void call_appid(struct afb_req request, const char *method)
145 const char *id = afb_req_value(request, _id_);
147 afb_req_fail(request, "bad-request", "missing 'id'");
150 memo = make_memo(request, method);
151 if (asprintf(&sid, "\"%s\"", id) <= 0 || memo == NULL) {
152 afb_req_fail(request, "server-error", "out of memory");
156 if (jbus_call_sj(jbus, method, sid, (void*)call_appid_callback, memo) < 0) {
157 afb_req_fail(request, "failed", "dbus failure");
163 static void call_runid(struct afb_req request, const char *method)
165 struct json_object *obj;
166 const char *id = afb_req_value(request, _runid_);
168 afb_req_fail(request, "bad-request", "missing 'runid'");
171 obj = jbus_call_sj_sync(jbus, method, id);
172 if (interface->verbosity)
173 fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, id,
174 obj ? json_object_to_json_string(obj) : "NULL");
176 afb_req_fail(request, "failed", "framework daemon failure");
179 obj = json_object_get(obj);
180 afb_req_success(request, obj, NULL);
183 /************************** entries ******************************/
185 static void runnables(struct afb_req request)
187 embed_call_void(request, _runnables_);
190 static void detail(struct afb_req request)
192 call_appid(request, _detail_);
195 static void start(struct afb_req request)
197 struct json_object *obj;
198 const char *id, *mode;
203 id = afb_req_value(request, _id_);
205 afb_req_fail(request, "bad-request", "missing 'id'");
209 mode = afb_req_value(request, _mode_);
210 if (mode == NULL || !strcmp(mode, _auto_)) {
211 mode = interface->mode == AFB_MODE_REMOTE ? _remote_ : _local_;
214 /* create the query */
215 rc = asprintf(&query, "{\"id\":\"%s\",\"mode\":\"%s\"}", id, mode);
217 afb_req_fail(request, "server-error", "out of memory");
221 /* calls the service */
222 obj = jbus_call_sj_sync(jbus, _start_, query);
223 if (interface->verbosity)
224 fprintf(stderr, "(afm-main-plugin) start(%s) -> %s\n", query,
225 obj ? json_object_to_json_string(obj) : "NULL");
229 obj = json_object_get(obj);
231 afb_req_fail(request, "failed", "framework daemon failure");
235 /* embed if needed */
236 if (json_object_get_type(obj) == json_type_int)
237 obj = embed(_runid_, obj);
238 afb_req_success(request, obj, NULL);
241 static void terminate(struct afb_req request)
243 call_runid(request, _terminate_);
246 static void stop(struct afb_req request)
248 call_runid(request, _stop_);
251 static void continue_(struct afb_req request)
253 call_runid(request, _continue_);
256 static void runners(struct afb_req request)
258 embed_call_void(request, _runners_);
261 static void state(struct afb_req request)
263 call_runid(request, _state_);
266 static void install(struct afb_req request)
268 struct json_object *obj, *added;
270 const char *filename;
273 /* get the argument */
274 arg = afb_req_get(request, "widget");
276 if (filename == NULL) {
277 afb_req_fail(request, "bad-request", "missing 'widget' file");
281 /* makes the query */
282 if (0 >= asprintf(&query, "\"%s\"", filename)) {
283 afb_req_fail(request, "server-error", "out of memory");
287 obj = jbus_call_sj_sync(jbus, _install_, query);
288 if (interface->verbosity)
289 fprintf(stderr, "(afm-main-plugin) install(%s) -> %s\n", query,
290 obj ? json_object_to_json_string(obj) : "NULL");
295 afb_req_fail(request, "failed", "framework daemon failure");
299 /* embed if needed */
300 if (json_object_object_get_ex(obj, _added_, &added))
302 obj = json_object_get(obj);
303 obj = embed(_id_, obj);
304 afb_req_success(request, obj, NULL);
307 static void uninstall(struct afb_req request)
309 call_appid(request, _uninstall_);
312 static const struct AFB_restapi plug_apis[] =
314 {_runnables_, AFB_SESSION_CHECK, runnables, "Get list of runnable applications"},
315 {_detail_ , AFB_SESSION_CHECK, detail, "Get the details for one application"},
316 {_start_ , AFB_SESSION_CHECK, start, "Start an application"},
317 {_terminate_, AFB_SESSION_CHECK, terminate, "Terminate a running application"},
318 {_stop_ , AFB_SESSION_CHECK, stop, "Stop (pause) a running application"},
319 {_continue_ , AFB_SESSION_CHECK, continue_, "Continue (resume) a stopped application"},
320 {_runners_ , AFB_SESSION_CHECK, runners, "Get the list of running applications"},
321 {_state_ , AFB_SESSION_CHECK, state, "Get the state of a running application"},
322 {_install_ , AFB_SESSION_CHECK, install, "Install an application using a widget file"},
323 {_uninstall_, AFB_SESSION_CHECK, uninstall, "Uninstall an application"},
324 { NULL, 0, NULL, NULL }
327 static const struct AFB_plugin plug_desc = {
328 .type = AFB_PLUGIN_JSON,
329 .info = "Application Framework Master Service",
330 .prefix = "afm-main",
334 static struct sbus_itf sbusitf;
336 const struct AFB_plugin *pluginRegister(const struct AFB_interface *itf)
339 struct afb_pollmgr pollmgr;
342 /* records the interface */
343 assert (interface == NULL);
345 evmgr = afb_daemon_get_evmgr(itf->daemon);
347 /* creates the sbus for session */
348 pollmgr = afb_daemon_get_pollmgr(itf->daemon);
349 sbusitf.wait = pollmgr.itf->wait;
350 sbusitf.open = pollmgr.itf->open;
351 sbusitf.on_readable = pollmgr.itf->on_readable;
352 sbusitf.on_writable = pollmgr.itf->on_writable;
353 sbusitf.on_hangup = pollmgr.itf->on_hangup;
354 sbusitf.close = pollmgr.itf->close;
355 sbus = sbus_session(&sbusitf, pollmgr.closure);
357 fprintf(stderr, "ERROR: %s:%d: can't connect to DBUS session\n", __FILE__, __LINE__);
361 /* creates the jbus for accessing afm-user-daemon */
362 jbus = create_jbus(sbus, "/org/AGL/afm/user");
368 /* records the signal handler */
369 rc = jbus_on_signal_s(jbus, _changed_, application_list_changed, NULL);