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) */
22 #include <json-c/json.h>
24 #include "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 *interface;
49 static struct afb_evmgr evmgr;
51 static struct jbus *jbus;
55 struct afb_req request;
59 static struct memo *make_memo(struct afb_req request, const char *method)
61 struct memo *memo = malloc(sizeof *memo);
63 memo->request = request;
64 memo->method = method;
65 afb_req_addref(request);
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);
113 afb_req_unref(memo->request);
117 static void embed_call_void(struct afb_req request, const char *method)
119 struct memo *memo = make_memo(request, method);
121 afb_req_fail(request, "failed", "out of memory");
122 else if (jbus_call_sj(jbus, method, "true", (void*)embed_call_void_callback, memo) < 0) {
123 afb_req_fail(request, "failed", "dbus failure");
128 static void call_appid_callback(int status, struct json_object *obj, struct memo *memo)
130 if (interface->verbosity)
131 fprintf(stderr, "(afm-main-plugin) %s -> %s\n", memo->method,
132 obj ? json_object_to_json_string(obj) : "NULL");
134 afb_req_fail(memo->request, "failed", "framework daemon failure");
136 obj = json_object_get(obj);
137 afb_req_success(memo->request, obj, NULL);
139 afb_req_unref(memo->request);
143 static void call_appid(struct afb_req request, const char *method)
147 const char *id = afb_req_value(request, _id_);
149 afb_req_fail(request, "bad-request", "missing 'id'");
152 memo = make_memo(request, method);
153 if (asprintf(&sid, "\"%s\"", id) <= 0 || memo == NULL) {
154 afb_req_fail(request, "server-error", "out of memory");
158 if (jbus_call_sj(jbus, method, sid, (void*)call_appid_callback, memo) < 0) {
159 afb_req_fail(request, "failed", "dbus failure");
165 static void call_runid(struct afb_req request, const char *method)
167 struct json_object *obj;
168 const char *id = afb_req_value(request, _runid_);
170 afb_req_fail(request, "bad-request", "missing 'runid'");
173 obj = jbus_call_sj_sync(jbus, method, id);
174 if (interface->verbosity)
175 fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, id,
176 obj ? json_object_to_json_string(obj) : "NULL");
178 afb_req_fail(request, "failed", "framework daemon failure");
181 obj = json_object_get(obj);
182 afb_req_success(request, obj, NULL);
185 /************************** entries ******************************/
187 static void runnables(struct afb_req request)
189 embed_call_void(request, _runnables_);
192 static void detail(struct afb_req request)
194 call_appid(request, _detail_);
197 static void start(struct afb_req request)
199 struct json_object *obj;
200 const char *id, *mode;
205 id = afb_req_value(request, _id_);
207 afb_req_fail(request, "bad-request", "missing 'id'");
211 mode = afb_req_value(request, _mode_);
212 if (mode == NULL || !strcmp(mode, _auto_)) {
213 mode = interface->mode == AFB_MODE_REMOTE ? _remote_ : _local_;
216 /* create the query */
217 rc = asprintf(&query, "{\"id\":\"%s\",\"mode\":\"%s\"}", id, mode);
219 afb_req_fail(request, "server-error", "out of memory");
223 /* calls the service */
224 obj = jbus_call_sj_sync(jbus, _start_, query);
225 if (interface->verbosity)
226 fprintf(stderr, "(afm-main-plugin) start(%s) -> %s\n", query,
227 obj ? json_object_to_json_string(obj) : "NULL");
231 obj = json_object_get(obj);
233 afb_req_fail(request, "failed", "framework daemon failure");
237 /* embed if needed */
238 if (json_object_get_type(obj) == json_type_int)
239 obj = embed(_runid_, obj);
240 afb_req_success(request, obj, NULL);
243 static void terminate(struct afb_req request)
245 call_runid(request, _terminate_);
248 static void stop(struct afb_req request)
250 call_runid(request, _stop_);
253 static void continue_(struct afb_req request)
255 call_runid(request, _continue_);
258 static void runners(struct afb_req request)
260 embed_call_void(request, _runners_);
263 static void state(struct afb_req request)
265 call_runid(request, _state_);
268 static void install(struct afb_req request)
270 struct json_object *obj, *added;
272 const char *filename;
275 /* get the argument */
276 arg = afb_req_get(request, "widget");
278 if (filename == NULL) {
279 afb_req_fail(request, "bad-request", "missing 'widget' file");
283 /* makes the query */
284 if (0 >= asprintf(&query, "\"%s\"", filename)) {
285 afb_req_fail(request, "server-error", "out of memory");
289 obj = jbus_call_sj_sync(jbus, _install_, query);
290 if (interface->verbosity)
291 fprintf(stderr, "(afm-main-plugin) install(%s) -> %s\n", query,
292 obj ? json_object_to_json_string(obj) : "NULL");
297 afb_req_fail(request, "failed", "framework daemon failure");
301 /* embed if needed */
302 if (json_object_object_get_ex(obj, _added_, &added))
304 obj = json_object_get(obj);
305 obj = embed(_id_, obj);
306 afb_req_success(request, obj, NULL);
309 static void uninstall(struct afb_req request)
311 call_appid(request, _uninstall_);
314 static const struct AFB_restapi plug_apis[] =
316 {_runnables_, AFB_SESSION_CHECK, runnables, "Get list of runnable applications"},
317 {_detail_ , AFB_SESSION_CHECK, detail, "Get the details for one application"},
318 {_start_ , AFB_SESSION_CHECK, start, "Start an application"},
319 {_terminate_, AFB_SESSION_CHECK, terminate, "Terminate a running application"},
320 {_stop_ , AFB_SESSION_CHECK, stop, "Stop (pause) a running application"},
321 {_continue_ , AFB_SESSION_CHECK, continue_, "Continue (resume) a stopped application"},
322 {_runners_ , AFB_SESSION_CHECK, runners, "Get the list of running applications"},
323 {_state_ , AFB_SESSION_CHECK, state, "Get the state of a running application"},
324 {_install_ , AFB_SESSION_CHECK, install, "Install an application using a widget file"},
325 {_uninstall_, AFB_SESSION_CHECK, uninstall, "Uninstall an application"},
326 { NULL, 0, NULL, NULL }
329 static const struct AFB_plugin plug_desc = {
330 .type = AFB_PLUGIN_JSON,
331 .info = "Application Framework Master Service",
332 .prefix = "afm-main",
336 const struct AFB_plugin *pluginRegister(const struct AFB_interface *itf)
341 /* records the interface */
342 assert (interface == NULL);
344 evmgr = afb_daemon_get_evmgr(itf->daemon);
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);