updates http related fucntions to get response code
[apps/native/tizen-things-daemon.git] / daemon / src / tizen-things-daemon.c
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.1 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <glib.h>
20 #include <glib-unix.h>
21 #include "ttd-log.h"
22 #include "ttd-cloud-conn-state.h"
23 #include "ttd-cmd.h"
24 #include "ttd-queue.h"
25 #include "ttd-conn-mgr.h"
26 #include "ttd-task.h"
27 #include "ttd-http.h"
28 #include "ttd-parse-cmd.h"
29 #include "ttd-worker-interface.h"
30 #include "ttd-worker-handle.h"
31 #include "common-util.h"
32
33 #ifndef SERVER_URL
34 /* TODO : remove it after test */
35 #define TEST_SERVER_URL "http://test.showiot.xyz/api/cmd?&target=test-page-device&owner=test-page&state=created"
36 #define SERVER_URL TEST_SERVER_URL
37 #endif
38
39 typedef struct __ttd_data {
40         GMainLoop *mainloop;
41         GThreadPool *thread_pool;
42         worker_interface_h worker_itf_h;
43 } ttd_data;
44
45 static gboolean __daemon_job_handler(gpointer data);
46 static gboolean __cloud_try_connect(gpointer data);
47
48 static unsigned long long _get_monotonic_time(void)
49 {
50         unsigned long long m_time = 0;
51         m_time  = common_get_monotonic_time();
52         if (m_time == 0)
53                 _E("failed to get monotonic time");
54
55         return m_time;
56 }
57
58 static const char *__ttd_get_cloud_url(void)
59 {
60         const char *url = NULL;
61
62         /* TODO : get cloud url */
63         url = SERVER_URL;
64
65         return url;
66 }
67
68 static gboolean _handle_sigint(gpointer data)
69 {
70         ttd_data *d_data = data;
71
72         _I("SIGINT received");
73
74         if (d_data && d_data->mainloop)
75                 g_main_loop_quit(d_data->mainloop);
76
77         return FALSE;
78 }
79
80 static gboolean _handle_sigterm(gpointer data)
81 {
82         ttd_data *d_data = data;
83
84         _I("SIGTERM received");
85
86         if (d_data && d_data->mainloop)
87                 g_main_loop_quit(d_data->mainloop);
88
89         return FALSE;
90 }
91
92 static void __main_thread_pool_func(gpointer thread_data, gpointer pool_data)
93 {
94         ttd_task *task = thread_data;
95         int ret = 0;
96
97         retm_if(!task, "task is NULL");
98
99         ret = ttd_task_run(task);
100         if (ret)
101                 _E("Failed to ttd_task_func_run()");
102
103         ttd_task_free(task);
104 }
105
106 static ttd_task_func __get_task_func(ttd_cmd_data *cmd)
107 {
108         ttd_task_func func = NULL;
109         retv_if(!cmd, NULL);
110
111         switch (ttd_cmd_get_type(cmd)) {
112         case TTD_CMD_TYPE_POWER:
113                 break;
114         case TTD_CMD_TYPE_CONFIG:
115                 break;
116         case TTD_CMD_TYPE_PACKAGE:
117         case TTD_CMD_TYPE_INFO:
118                 func = ttd_worker_launch;
119                 break;
120         case TTD_CMD_TYPE_DIAGNOSIS:
121                 break;
122         case TTD_CMD_TYPE_LOCAL:
123                 break;
124         case TTD_CMD_TYPE_UNKNOWN:
125         case TTD_CMD_TYPE_MAX:
126         default:
127                 break;
128         }
129
130         return func;
131 }
132 static gboolean __daemon_job_handler(gpointer data)
133 {
134         ttd_data *d_data = data;
135
136         ttd_cmd_data *cmd_data = NULL;
137         ttd_result_data_s *res_data = NULL;
138
139         if (!data) {
140                 /* Must not reach here */
141                 _E("data is NULL, daemon will be stop");
142                 abort();
143                 return FALSE;
144         }
145
146         res_data = ttd_queue_timeout_pop(TTD_QUEUE_TYPE_RESULT, 500);
147         if (res_data) {
148                 /* Do something, handles result...jfkdjlfjklajflkdsjfkdslajfkdlsjlk */
149                 /* pushes new task? or creates new command? */
150         }
151
152         cmd_data = ttd_queue_timeout_pop(TTD_QUEUE_TYPE_CMD, 500);
153         if (cmd_data) {
154                 ttd_task *new_task = NULL;
155                 ttd_task_func func = NULL;
156                 /* Do something, creates task... */
157                 func = __get_task_func(cmd_data);
158                 if (!func) {
159                         _E("task func is not defined - type[%d]",
160                                 ttd_cmd_get_type(cmd_data));
161
162                         ttd_cmd_free(cmd_data);
163                         return TRUE;
164                 }
165
166                 new_task = ttd_task_new(TTD_TASK_PRIORITY_NORMAL, func,
167                         cmd_data, (ttd_task_data_free_func)ttd_cmd_free);
168
169                 g_thread_pool_push(d_data->thread_pool, new_task, NULL);
170         }
171         return TRUE;
172 }
173
174 static int __say_hello_to_cloud(void *data)
175 {
176         int ret  = 0;
177         char *cmd = NULL;
178         long res_code = 0;
179
180         ret = ttd_http_get_cloud_cmd(__ttd_get_cloud_url(), &cmd, &res_code);
181         retvm_if(ret, -1, "failed to get cmd [%ld]", res_code);
182
183         if (cmd) {
184                 GList *cmd_list = NULL;
185                 GList *l = NULL;
186
187                 ttd_parse_json_to_cmd(cmd, &cmd_list);
188                 for (l = cmd_list; l != NULL; l = l->next) {
189                         ttd_cmd_data *cmd_data = NULL;
190
191                         cmd_data = (ttd_cmd_data *)l->data;
192                         if (cmd_data)
193                                 ttd_queue_push(TTD_QUEUE_TYPE_CMD,
194                                         cmd_data, (ttd_queue_item_free_func)ttd_cmd_free);
195                 }
196         } else
197                 _D("there is no cmd now");
198
199         return 0;
200 }
201
202 /*********** FIXME *************/
203 static gboolean __cloud_try_connect(gpointer data)
204 {
205         int ret = 0;
206         ttd_data *d_data = data;
207
208         if (!data) {
209                 /* Must not reach here */
210                 _E("data is NULL, daemon will be stop");
211                 abort();
212         }
213         ret = __say_hello_to_cloud(data);
214
215         if (!ret) {
216                 ttd_cloud_conn_state_set(TTD_CLOUD_CONN_STATE_CONNECTED);
217                 g_idle_add(__daemon_job_handler, d_data);
218         } else /* endless retry? */
219                 g_timeout_add_seconds(3, __cloud_try_connect, data);
220
221         return FALSE;
222 }
223
224 static gboolean __do_device_register(gpointer data)
225 {
226         int registered = 0;
227         ttd_data *d_data = data;
228
229         if (!d_data) {
230                 /* Must not reach here */
231                 _E("data is NULL, daemon will be stop");
232                 abort();
233         }
234
235         /*      TODO
236                 - check device ID
237                 - check token or auth key
238         */
239
240         if (!registered) {
241                 /* TODO : start easy setup procedure here !! */
242         }
243
244         ttd_cloud_conn_state_set(TTD_CLOUD_CONN_STATE_CONNECTABLE);
245         __cloud_try_connect(data); /* ???? */
246
247         return FALSE;
248 }
249
250 int main(int argc, char* argv[])
251 {
252         ttd_data *d_data = NULL;
253         unsigned long long start = 0;
254
255         start = _get_monotonic_time();
256
257         d_data = calloc(1, sizeof(ttd_data));
258
259         log_type_set(LOG_TYPE_DLOG);
260
261         d_data->mainloop = g_main_loop_new(NULL, FALSE);
262
263         /* TODO : prepare to start daemon */
264         g_unix_signal_add(SIGINT, _handle_sigint, d_data);
265         g_unix_signal_add(SIGTERM, _handle_sigterm, d_data);
266
267         ttd_queue_init();
268         ttd_conn_mgr_init();
269         ttd_http_init();
270         ttd_cloud_conn_state_set(TTD_CLOUD_CONN_STATE_DISCONNECTED);
271
272         if (ttd_worker_interface_init(&(d_data->worker_itf_h)) < 0)
273                 _E("Failed to initialize worker interface");
274
275         d_data->thread_pool =
276                 g_thread_pool_new(__main_thread_pool_func, d_data, -1, FALSE, NULL);
277         g_thread_pool_set_sort_function(
278                 d_data->thread_pool, ttd_task_sort_func, NULL);
279
280         _D("[delay] start-to-ready - %.3lf(ms)",
281                 (double)(_get_monotonic_time() - start)/1000);
282         g_idle_add(__do_device_register, d_data);
283
284         g_main_loop_run(d_data->mainloop);
285
286         g_main_loop_unref(d_data->mainloop);
287         g_thread_pool_free(d_data->thread_pool, FALSE, TRUE);
288
289         ttd_worker_interface_fini(d_data->worker_itf_h);
290
291         free(d_data);
292         d_data = NULL;
293
294         ttd_queue_fini();
295         ttd_conn_mgr_fini();
296         ttd_http_fini();
297
298         log_file_close();
299
300         return 0;
301 }