Sending lap time to cloud
[apps/native/gear-racing-car.git] / src / cloud / cloud_lap_request.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 "cloud/cloud_lap_request.h"
18 #include "cloud/http_request.h"
19 #include "cloud/lap_info_serializer.h"
20 #include "cloud/lap_info.h"
21 #include <glib.h>
22 #include <gio/gio.h>
23 #include <string.h>
24 #include "log.h"
25
26 #define BASE_URL "http://son.tizen.online"
27 #define PATH_API_LAP "/api/lap"
28
29 typedef struct {
30         char *ap_mac;
31         cloud_request_lap_list_data_cb cb;
32         void *user_data;
33 } lap_api_get_request_context_t;
34
35 typedef struct {
36         lap_info_t *lap;
37         cloud_request_lap_post_finish_cb cb;
38         void *user_data;
39 } lap_api_post_request_context_t;
40
41 typedef struct {
42         long response_code;
43         char *response_msg;
44 } lap_api_post_request_response_t;
45
46 typedef struct {
47         long response_code;
48         lap_info_t **laps;
49         int size;
50 } lap_api_get_request_response_t;
51
52 static void lap_api_post_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable);
53 static void lap_api_post_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data);
54 static void lap_api_post_task_context_free(lap_api_post_request_context_t *context);
55 static void lap_api_post_request_response_free(lap_api_post_request_response_t *response);
56
57 static void lap_api_get_task_context_free(lap_api_get_request_context_t *context);
58 static void lap_api_get_request_response_free(lap_api_get_request_response_t *response);
59 static void lap_api_get_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable);
60 static void lap_api_get_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data);
61
62 #define G_ERROR_DOMAIN g_quark_from_static_string("cloud_lap_request")
63
64 GCancellable *cloud_lap_request_api_racing_get(const char *ap_mac, cloud_request_lap_list_data_cb cb, void *user_data)
65 {
66         GCancellable *cancellable = g_cancellable_new();
67
68         GTask *task = g_task_new(NULL, cancellable, lap_api_get_task_ready_cb, NULL);
69         g_task_set_source_tag(task, cloud_lap_request_api_racing_get);
70         g_task_set_return_on_cancel(task, FALSE);
71
72         lap_api_get_request_context_t *context = g_new0(lap_api_get_request_context_t, 1);
73         context->ap_mac = strndup(ap_mac, strlen(ap_mac));
74         context->cb = cb;
75         context->user_data = user_data;
76
77         g_task_set_task_data(task, context, (GDestroyNotify)lap_api_get_task_context_free);
78         g_task_run_in_thread(task, lap_api_get_task_thread_cb);
79
80         g_object_unref(task);
81
82         return cancellable;
83 }
84
85 GCancellable *cloud_lap_request_api_racing_post(const lap_info_t *lap_info, cloud_request_lap_post_finish_cb cb, void *user_data)
86 {
87         GCancellable *cancellable = g_cancellable_new();
88
89         GTask *task = g_task_new(NULL, cancellable, lap_api_post_task_ready_cb, NULL);
90         g_task_set_source_tag(task, cloud_lap_request_api_racing_post);
91         g_task_set_return_on_cancel(task, FALSE);
92
93         lap_api_post_request_context_t *context = g_new0(lap_api_post_request_context_t, 1);
94         context->lap = lap_info_copy(lap_info);
95         context->cb = cb;
96         context->user_data = user_data;
97
98         g_task_set_task_data(task, context, (GDestroyNotify)lap_api_post_task_context_free);
99         g_task_run_in_thread(task, lap_api_post_task_thread_cb);
100
101         g_object_unref(task);
102
103         return cancellable;
104 }
105
106 static void lap_api_post_task_context_free(lap_api_post_request_context_t *context)
107 {
108         ret_if(!context);
109
110         lap_info_destroy(context->lap);
111         g_free(context);
112 }
113
114 static void lap_api_post_request_response_free(lap_api_post_request_response_t *response)
115 {
116         ret_if(!response);
117
118         g_free(response->response_msg);
119         g_free(response);
120 }
121
122 static void lap_api_post_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable)
123 {
124         lap_api_post_request_context_t *context = (lap_api_post_request_context_t *)task_data;
125
126         if (g_task_return_error_if_cancelled(task)) {
127                 return;
128         }
129
130         lap_api_post_request_response_t *response = g_new0(lap_api_post_request_response_t, 1);
131
132         char *json = lap_info_serializer_serialize(context->lap);
133         int retval = http_request_post(BASE_URL""PATH_API_LAP, json, &(response->response_msg), &(response->response_code));
134         g_free(json);
135
136         if (retval != 0) {
137                 GError *err = g_error_new(G_ERROR_DOMAIN, retval, "http_request_post failed!");
138                 g_task_return_error(task, err);
139         }
140
141         g_task_return_pointer(task, response, (GDestroyNotify)lap_api_post_request_response_free);
142 }
143
144 static void lap_api_post_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
145 {
146         GTask *task = G_TASK(res);
147         GError *error = NULL;
148
149         //If no error occurred g_task_propagate_pointer transfers ownership, so later response have to be freed.
150         lap_api_post_request_response_t *response = g_task_propagate_pointer(task, &error);
151         if (error != NULL) {
152                 _E("POST async task failed with msg: %s", error->message);
153                 g_error_free(error);
154                 return;
155         }
156         lap_api_post_request_context_t *context = g_task_get_task_data(task);
157
158         bool result = (response->response_code == 200 && (strncmp(response->response_msg, "Success", strlen("Success")) == 0)) ?
159                 true :
160                 false;
161
162         if (context->cb) {
163                 context->cb(result, context->user_data);
164         }
165
166         lap_api_post_request_response_free(response);
167 }
168
169 static void lap_api_get_task_context_free(lap_api_get_request_context_t *context)
170 {
171         ret_if(!context);
172
173         g_free(context->ap_mac);
174         g_free(context);
175 }
176
177 static void lap_api_get_request_response_free(lap_api_get_request_response_t *response)
178 {
179         ret_if(!response);
180         ret_if(response->size <= 0);
181
182         for (int i = 0; i < response->size; i++)
183         {
184                 lap_info_destroy(response->laps[i]);
185         }
186         g_free(response->laps);
187         g_free(response);
188 }
189
190 static void lap_api_get_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable)
191 {
192         lap_api_get_request_context_t *context = (lap_api_get_request_context_t *)task_data;
193
194         if (g_task_return_error_if_cancelled(task)) {
195                 return;
196         }
197
198         lap_api_get_request_response_t *response = g_new0(lap_api_get_request_response_t, 1);
199         char *response_json = NULL;
200
201         GString *url = g_string_new(BASE_URL""PATH_API_LAP"?apMac=");
202         g_string_append(url, context->ap_mac);
203
204         int retval = http_request_get(url->str, &response_json, &(response->response_code));
205         g_string_free(url, TRUE);
206
207         if (retval != 0) {
208                 GError *err = g_error_new(G_ERROR_DOMAIN, retval, "http_request_get failed!");
209                 g_task_return_error(task, err);
210         }
211         else {
212                 response->laps = lap_info_serializer_deserialize_array(response_json, &(response->size));
213         }
214
215         g_free(response_json);
216         g_task_return_pointer(task, response, (GDestroyNotify)lap_api_get_request_response_free);
217 }
218
219 static void lap_api_get_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
220 {
221         GTask *task = G_TASK(res);
222         GError *error = NULL;
223
224         //If no error occurred g_task_propagate_pointer transfers ownership, so later response have to be freed.
225         lap_api_get_request_response_t *response = g_task_propagate_pointer(task, &error);
226         if (error != NULL) {
227                 _E("GET async task failed with msg: %s", error->message);
228                 g_error_free(error);
229                 return;
230         }
231         lap_api_get_request_context_t *context = g_task_get_task_data(task);
232
233         bool result = (response->response_code == 200) ? true : false;
234
235         if (context->cb) {
236                 context->cb(result, response->laps, response->size, context->user_data);
237         }
238
239         lap_api_get_request_response_free(response);
240 }