refactored verbosity
[src/app-framework-binder.git] / plugins / afm-main-plugin / afm-main-plugin.c
1 /*
2  * Copyright (C) 2015 "IoT.bzh"
3  * Author "Fulup Ar Foll"
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #define _GNU_SOURCE         /* See feature_test_macros(7) */
20 #include <stdio.h>
21 #include <string.h>
22 #include <json.h>
23
24 #include "afb-plugin.h"
25 #include "afb-req-itf.h"
26
27 #include "utils-jbus.h"
28
29 static const char _auto_[]      = "auto";
30 static const char _continue_[]  = "continue";
31 static const char _detail_[]    = "detail";
32 static const char _id_[]        = "id";
33 static const char _install_[]   = "install";
34 static const char _local_[]     = "local";
35 static const char _mode_[]      = "mode";
36 static const char _remote_[]    = "remote";
37 static const char _runid_[]     = "runid";
38 static const char _runnables_[] = "runnables";
39 static const char _runners_[]   = "runners";
40 static const char _start_[]     = "start";
41 static const char _state_[]     = "state";
42 static const char _stop_[]      = "stop";
43 static const char _terminate_[] = "terminate";
44 static const char _uninstall_[] = "uninstall";
45 static const char _uri_[]       = "uri";
46
47 static const struct AFB_interface *interface;
48
49 static struct jbus *jbus;
50
51 static struct json_object *embed(const char *tag, struct json_object *obj)
52 {
53         struct json_object *result;
54
55         if (obj == NULL)
56                 result = NULL;
57         else if (!tag)
58                 result = obj;
59         else {
60                 result = json_object_new_object();
61                 if (result == NULL) {
62                         /* can't embed */
63                         result = obj;
64                 }
65                 else {
66                         /* TODO why is json-c not returning a status? */
67                         json_object_object_add(result, tag, obj);
68                 }
69         }
70         return result;
71 }
72
73 static void embed_call_void(struct afb_req request, const char *method)
74 {
75         struct json_object *obj = jbus_call_sj_sync(jbus, method, "true");
76         if (interface->verbosity)
77                 fprintf(stderr, "(afm-main-plugin) %s(true) -> %s\n", method, obj ? json_object_to_json_string(obj) : "NULL");
78         if (obj == NULL) {
79                 afb_req_fail(request, "failed", "framework daemon failure");
80                 return;
81         }
82         obj = embed(method, obj);
83         if (obj == NULL) {
84                 afb_req_fail(request, "failed", "framework daemon failure");
85                 return;
86         }
87         afb_req_success(request, obj, NULL);
88 }
89
90 static void call_appid(struct afb_req request, const char *method)
91 {
92         struct json_object *obj;
93         char *sid;
94         const char *id = afb_req_argument(request, _id_);
95         if (id == NULL) {
96                 afb_req_fail(request, "bad-request", "missing 'id'");
97                 return;
98         }
99         if (asprintf(&sid, "\"%s\"", id) <= 0) {
100                 afb_req_fail(request, "server-error", "out of memory");
101                 return;
102         }
103         obj = jbus_call_sj_sync(jbus, method, sid);
104         if (interface->verbosity)
105                 fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, sid, obj ? json_object_to_json_string(obj) : "NULL");
106         free(sid);
107         if (obj == NULL) {
108                 afb_req_fail(request, "failed", "framework daemon failure");
109                 return;
110         }
111         afb_req_success(request, obj, NULL);
112 }
113
114 static void call_runid(struct afb_req request, const char *method)
115 {
116         struct json_object *obj;
117         const char *id = afb_req_argument(request, _runid_);
118         if (id == NULL) {
119                 afb_req_fail(request, "bad-request", "missing 'runid'");
120                 return;
121         }
122         obj = jbus_call_sj_sync(jbus, method, id);
123         if (interface->verbosity)
124                 fprintf(stderr, "(afm-main-plugin) %s(%s) -> %s\n", method, id,
125                                 obj ? json_object_to_json_string(obj) : "NULL");
126         if (obj == NULL) {
127                 afb_req_fail(request, "failed", "framework daemon failure");
128                 return;
129         }
130         afb_req_success(request, obj, NULL);
131 }
132
133
134 /************************** entries ******************************/
135
136 static void runnables(struct afb_req request)
137 {
138         embed_call_void(request, _runnables_);
139 }
140
141 static void detail(struct afb_req request)
142 {
143         call_appid(request, _detail_);
144 }
145
146 static void start(struct afb_req request)
147 {
148         struct json_object *obj;
149         const char *id, *mode;
150         char *query;
151         int rc;
152
153         /* get the id */
154         id = afb_req_argument(request, _id_);
155         if (id == NULL) {
156                 afb_req_fail(request, "bad-request", "missing 'id'");
157                 return;
158         }
159         /* get the mode */
160         mode = afb_req_argument(request, _mode_);
161         if (mode == NULL || !strcmp(mode, _auto_)) {
162                 mode = interface->mode == AFB_MODE_REMOTE ? _remote_ : _local_;
163         }
164
165         /* create the query */
166         rc = asprintf(&query, "{\"id\":\"%s\",\"mode\":\"%s\"}", id, mode);
167         if (rc < 0) {
168                 afb_req_fail(request, "server-error", "out of memory");
169                 return;
170         }
171
172         /* calls the service */
173         obj = jbus_call_sj_sync(jbus, _start_, query);
174         if (interface->verbosity)
175                 fprintf(stderr, "(afm-main-plugin) start(%s) -> %s\n", query, obj ? json_object_to_json_string(obj) : "NULL");
176         free(query);
177
178         /* check status */
179         if (obj == NULL) {
180                 afb_req_fail(request, "failed", "framework daemon failure");
181                 return;
182         }
183
184         /* embed if needed */
185         if (json_object_get_type(obj) == json_type_int)
186                 obj = embed(_runid_, obj);
187         afb_req_success(request, obj, NULL);
188 }
189
190 static void terminate(struct afb_req request)
191 {
192         call_runid(request, _terminate_);
193 }
194
195 static void stop(struct afb_req request)
196 {
197         call_runid(request, _stop_);
198 }
199
200 static void continue_(struct afb_req request)
201 {
202         call_runid(request, _continue_);
203 }
204
205 static void runners(struct afb_req request)
206 {
207         embed_call_void(request, _runners_);
208 }
209
210 static void state(struct afb_req request)
211 {
212         call_runid(request, _state_);
213 }
214
215 static void install(struct afb_req request)
216 {
217         struct json_object *obj;
218         char *query;
219         const char *filename;
220         struct afb_arg arg;
221
222         /* get the argument */
223         arg = afb_req_get(request, "widget");
224         filename = arg.value;
225         if (filename == NULL || !arg.is_file) {
226                 afb_req_fail(request, "bad-request", "missing 'widget' file");
227                 return;
228         }
229
230         /* makes the query */
231         if (0 >= asprintf(&query, "\"%s\"", filename)) {
232                 afb_req_fail(request, "server-error", "out of memory");
233                 return;
234         }
235
236         obj = jbus_call_sj_sync(jbus, _install_, query);
237         if (interface->verbosity)
238                 fprintf(stderr, "(afm-main-plugin) install(%s) -> %s\n", query, obj ? json_object_to_json_string(obj) : "NULL");
239         free(query);
240
241         /* check status */
242         if (obj == NULL) {
243                 afb_req_fail(request, "failed", "framework daemon failure");
244                 return;
245         }
246
247         /* embed if needed */
248         obj = embed(_id_, obj);
249         afb_req_success(request, obj, NULL);
250 }
251
252 static void uninstall(struct afb_req request)
253 {
254         call_appid(request, _uninstall_);
255 }
256
257 static const struct AFB_restapi plug_apis[] =
258 {
259         {_runnables_, AFB_SESSION_CHECK, runnables,  "Get list of runnable applications"},
260         {_detail_   , AFB_SESSION_CHECK, detail, "Get the details for one application"},
261         {_start_    , AFB_SESSION_CHECK, start, "Start an application"},
262         {_terminate_, AFB_SESSION_CHECK, terminate, "Terminate a running application"},
263         {_stop_     , AFB_SESSION_CHECK, stop, "Stop (pause) a running application"},
264         {_continue_ , AFB_SESSION_CHECK, continue_, "Continue (resume) a stopped application"},
265         {_runners_  , AFB_SESSION_CHECK, runners,  "Get the list of running applications"},
266         {_state_    , AFB_SESSION_CHECK, state, "Get the state of a running application"},
267         {_install_  , AFB_SESSION_CHECK, install,  "Install an application using a widget file"},
268         {_uninstall_, AFB_SESSION_CHECK, uninstall, "Uninstall an application"},
269         { NULL, 0, NULL, NULL }
270 };
271
272 static const struct AFB_plugin plug_desc = {
273         .type = AFB_PLUGIN_JSON,
274         .info = "Application Framework Master Service",
275         .prefix = "afm-main",
276         .apis = plug_apis
277 };
278
279 const struct AFB_plugin *pluginRegister(const struct AFB_interface *itf)
280 {
281         interface = itf;
282
283         jbus = create_jbus_session("/org/AGL/afm/user");
284         if (jbus)
285                 return &plug_desc;
286         fprintf(stderr, "ERROR: %s:%d: can't connect to DBUS session\n", __FILE__, __LINE__);
287         return NULL;
288 }
289