2cfc86c2faab7a52ac43100a9634416acc22d7ac
[apps/native/tizen-things-daemon.git] / lib / things-service-worker / src / ttd-worker-lib.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Contact: Junkyu Han <junkyu.han@samsung.com>
5  *
6  * Licensed under the Flora License, Version 1.1 (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
9  *
10  * http://floralicense.org/license/
11  *
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.
17  */
18
19 #include <glib.h>
20 #include <gio/gio.h>
21
22 #include "log-private.h"
23 #include "ttd-worker-lib.h"
24 #include "common-worker-inf-def.h"
25 #include "common-worker-inf-dbus.h"
26
27 struct _ttd_worker_report_s {
28         ttd_worker_submit_report_completed_cb completed_cb;
29         void *completed_cb_data;
30         char *cmd_id;
31         char *report_json;
32         ttd_worker_working_state_e state;
33 };
34
35 typedef struct {
36         GCancellable *cancellable;
37         TtdWorkerDbus *dbus_object;
38         unsigned int ref_count;
39 } worker_dbus_handle;
40
41 static worker_dbus_handle *g_dbus_handle = NULL;
42
43 static void __free_dbus_handle(worker_dbus_handle *handle)
44 {
45         if (!handle)
46                 return;
47
48         if (handle->cancellable) {
49                 g_cancellable_cancel(handle->cancellable);
50                 g_object_unref(handle->cancellable);
51         }
52
53         if (handle->dbus_object)
54                 g_object_unref(handle->dbus_object);
55
56         g_free(handle);
57 }
58
59 static void __unref_dbus_connection(void)
60 {
61         _D("Destory the DBus Connection");
62
63         if (!g_dbus_handle)
64                 return;
65
66         g_dbus_handle->ref_count--;
67
68         if (!g_dbus_handle->ref_count) {
69                 __free_dbus_handle(g_dbus_handle);
70                 g_dbus_handle = NULL;
71         }
72 }
73
74 static int __ref_dbus_connection(void)
75 {
76         worker_dbus_handle *handle = NULL;
77         GError *error = NULL;
78
79         if (g_dbus_handle) {
80                 g_dbus_handle->ref_count++;
81                 _D("DBus ref count : %u", g_dbus_handle->ref_count);
82                 return 0;
83         }
84
85         _D("Make a new DBus Connection");
86
87         handle = g_try_malloc0(sizeof(worker_dbus_handle));
88         if (!handle)
89                 return -1;
90
91         handle->cancellable = g_cancellable_new();
92
93         handle->dbus_object =
94                 ttd_worker_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
95                         G_DBUS_PROXY_FLAGS_NONE,
96                         TTD_WORKER_DBUS_NAME,
97                         TTD_WORKER_DBUS_OBJECT_PATH,
98                         handle->cancellable,
99                         &error);
100         if (!handle->dbus_object) {
101                 _E("Fail to create the proxy object because of %s", error->message);
102                 g_error_free(error);
103                 error = NULL;
104                 __free_dbus_handle(handle);
105                 return -1;
106         }
107
108         g_dbus_handle = handle;
109         g_dbus_handle->ref_count = 1;
110         _D("DBus ref count : %u", g_dbus_handle->ref_count);
111
112         return 0;
113 }
114
115 static void __submit_completed_cb(
116         GObject *source_object, GAsyncResult *res, gpointer user_data)
117 {
118         GError *error = NULL;
119         ttd_worker_report *report = user_data;
120         gint ret_val = -1;
121         gboolean ret = FALSE;
122         ttd_worker_submit_result_e result;
123
124         _D("Send completed");
125         ret = ttd_worker_dbus_call_ttd_worker_submit_report_finish(
126                         g_dbus_handle->dbus_object, &ret_val, res, &error);
127         if (!ret) {
128                 _E("DBus proxy call is failed[%s]", error->message);
129                 result = TTD_WORKER_SUBMIT_FAIL;
130                 g_error_free(error);
131         } else {
132                 if (ret_val < 0) {
133                         _E("Submit report is failed");
134                         result = TTD_WORKER_SUBMIT_FAIL;
135                 } else
136                         result = TTD_WORKER_SUBMIT_SUCCESS;
137         }
138
139         if (report && report->completed_cb)
140                 report->completed_cb(result, report, report->completed_cb_data);
141 }
142
143 void __free_report(ttd_worker_report *report)
144 {
145         if (!report)
146                 return;
147
148         g_free(report->cmd_id);
149         g_free(report->report_json);
150         g_free(report);
151 }
152
153 ttd_worker_report *__alloc_new_report(void)
154 {
155         ttd_worker_report *re = NULL;
156
157         re = g_try_malloc0(sizeof(ttd_worker_report));
158         retvm_if(!re, NULL, "failed to alloc report");
159
160         re->state = TTD_WORKER_STATE_UNKNOWN;
161
162         if (__ref_dbus_connection()) {
163                 __free_report(re);
164                 return NULL;
165         }
166
167         return re;
168 }
169
170 ttd_worker_report *ttd_worker_report_new(void)
171 {
172         return __alloc_new_report();
173 }
174
175 ttd_worker_report *ttd_worker_report_new_by_cmd_id(const char *cmd_id)
176 {
177         ttd_worker_report *report = NULL;
178
179         report = __alloc_new_report();
180         if (report)
181                 report->cmd_id = g_strdup(cmd_id);
182
183         return report;
184 }
185
186 void ttd_worker_report_free(ttd_worker_report *report)
187 {
188         __free_report(report);
189         __unref_dbus_connection();
190 }
191
192 int ttd_worker_report_set_cmd_id(ttd_worker_report *report, const char *cmd_id)
193 {
194         retvm_if(!report, -1, "report is NULL");
195
196         g_free(report->cmd_id);
197
198         if (cmd_id)
199                 report->cmd_id = g_strdup(cmd_id);
200         else
201                 _D("unset cmd id");
202
203         return 0;
204 }
205
206 int ttd_worker_report_set_working_state(
207         ttd_worker_report *report, ttd_worker_working_state_e state)
208 {
209         retvm_if(!report, -1, "report is NULL");
210
211         report->state = state;
212
213         return 0;
214 }
215
216 /* report_data should be JSON format */
217 int ttd_worker_report_set_report_data(
218         ttd_worker_report *report, const char *report_data)
219 {
220         retvm_if(!report, -1, "report is NULL");
221
222         g_free(report->report_json);
223
224         if (report_data)
225                 report->report_json = g_strdup(report_data);
226         else
227                 _D("unset report_json");
228
229         return 0;
230 }
231
232 int ttd_worker_report_get_cmd_id(
233         ttd_worker_report *report, const char **cmd_id)
234 {
235         retvm_if(!report, -1, "report is NULL");
236         retvm_if(!cmd_id, -1, "cmd_id is NULL");
237
238         *cmd_id = (const char *)report->cmd_id;
239
240         return 0;
241 }
242
243 int ttd_worker_report_get_working_state(
244         ttd_worker_report *report, ttd_worker_working_state_e *state)
245 {
246         retvm_if(!report, -1, "report is NULL");
247         retvm_if(!state, -1, "state is NULL");
248
249         *state = report->state;
250
251         return 0;
252 }
253
254 int ttd_worker_report_get_report_data(
255         ttd_worker_report *report, const char **report_data)
256 {
257         retvm_if(!report, -1, "report is NULL");
258         retvm_if(!report_data, -1, "report_data is NULL");
259
260         *report_data = (const char *)report->report_json;
261
262         return 0;
263 }
264
265 int ttd_worker_submit_report(ttd_worker_report *report,
266                 ttd_worker_submit_report_completed_cb completed_cb,
267                 void *completed_cb_data)
268 {
269         ttd_worker_report *rep = NULL;
270         retvm_if(!g_dbus_handle->dbus_object, -1, "dbus_object is NULL");
271         retvm_if(!report, -1, "report is NULL");
272         retvm_if(!report->cmd_id, -1, "cmd_id is NULL");
273         retvm_if(!report->report_json, -1, "report data is NULL");
274         retvm_if(report->state == TTD_WORKER_STATE_UNKNOWN, -1, "state is UNKNOWN");
275
276         if (completed_cb)
277                 rep = report;
278
279         report->completed_cb = completed_cb;
280         report->completed_cb_data = completed_cb_data;
281
282         ttd_worker_dbus_call_ttd_worker_submit_report(
283                         g_dbus_handle->dbus_object,
284                         report->cmd_id,
285                         report->report_json,
286                         report->state,
287                         g_dbus_handle->cancellable,
288                         (GAsyncReadyCallback) __submit_completed_cb,
289                         rep);
290
291         return 0;
292 }
293
294 int ttd_worker_submit_report_sync(
295         ttd_worker_report *report, ttd_worker_submit_result_e *result)
296 {
297         GError *error = NULL;
298         gint ret_val = -1;
299         gboolean ret = FALSE;
300         ttd_worker_submit_result_e res = TTD_WORKER_SUBMIT_SUCCESS;
301
302         if (result)
303                 *result = TTD_WORKER_SUBMIT_FAIL;
304
305         retvm_if(!g_dbus_handle->dbus_object, -1, "dbus_object is NULL");
306         retvm_if(!report, -1, "report is NULL");
307         retvm_if(!report->cmd_id, -1, "cmd_id is NULL");
308         retvm_if(!report->report_json, -1, "report data is NULL");
309         retvm_if(report->state == TTD_WORKER_STATE_UNKNOWN, -1, "state is UNKNOWN");
310
311         ret = ttd_worker_dbus_call_ttd_worker_submit_report_sync(
312                         g_dbus_handle->dbus_object,
313                         report->cmd_id,
314                         report->report_json,
315                         report->state,
316                         &ret_val,
317                         g_dbus_handle->cancellable,
318                         &error);
319         if (!ret) {
320                 _E("DBus proxy call is failed[%s]", error->message);
321                 g_error_free(error);
322                 res = TTD_WORKER_SUBMIT_FAIL;
323         } else {
324                 if (ret_val < 0) {
325                         _E("Submit report is failed");
326                         res = TTD_WORKER_SUBMIT_FAIL;
327                 }
328         }
329
330         if (result)
331                 *result = res;
332
333         return 0;
334 }