Fix a crash
[framework/location/libdecarta.git] / decarta / decarta_directory.c
1 /*
2  * libdecarta
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <glib.h>
23 #include <stdbool.h>
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 #include "decarta_log.h"
28 #include "decarta_config.h"
29 #include "http_wrapper.h"
30 #include "decarta_xml.h"
31 #include "decarta_directory.h"
32
33 static GHashTable *http_reqid_hash = NULL;
34
35 typedef struct {
36         DecartaDirectoryCB callback;
37         void *userdata;
38         guint request_id; /**< used to remove from table after success */
39 } DecartaDirCBData;
40
41 static gboolean
42 __directory_del_table_node_cb(gpointer key,
43         gpointer value,
44         gpointer user_data)
45 {
46         if (!user_data || !key || !value) {
47                 return false;
48         }
49         HttpHandle http_async = NULL;
50
51         http_async = (HttpHandle)value;
52         char *user_key = (char *)user_data;
53         char *table_key = (char *)key;
54
55         if (!g_strcmp0(user_key, table_key)) {
56                 DECARTA_LOGD("req_id [%s] http_async [%d] closed!", table_key, http_async);
57                 g_free(table_key);
58                 http_close(http_async);
59                 return true;
60         }
61         DECARTA_LOGD("req_id [%s] http_async [%d] not close", table_key, http_async);
62         return false;
63 }
64
65
66 static void
67 search_directory_cb (gboolean success,
68         char *recv_data,
69         void *user_data)
70 {
71         DECARTA_LOGD("search_directory_cb");
72         DecartaDirCBData* cb_data = (DecartaDirCBData*)user_data;
73         DecartaError err = DECARTA_ERROR_NONE;
74         gchar *req_id_str = NULL;
75         GList *poi_list = NULL;
76         gchar *error_code = NULL;
77         gchar *error_msg = NULL;
78
79         if (success != TRUE) {
80                 err = DECARTA_ERROR_HTTP;
81         } else if (!xml_directory_parse(recv_data, &poi_list, &req_id_str, &error_code, &error_msg)) {
82                 if (g_str_has_prefix(error_msg, "POI not found") == TRUE) {
83                         err = DECARTA_ERROR_NOT_FOUND;
84                 } else {
85                         err = DECARTA_ERROR_XML;
86                 }
87         }
88
89         if (cb_data && cb_data->callback) cb_data->callback (err, req_id_str, poi_list, error_code, error_msg, cb_data->userdata);
90
91         /** remove the success request id from hash table */
92         char *request_id_str = g_strdup_printf("%u", cb_data->request_id);
93         if (http_reqid_hash) {
94                 DECARTA_LOGD("remove the http async after success!");
95                 g_hash_table_foreach_remove(http_reqid_hash, (GHRFunc)__directory_del_table_node_cb, (gpointer)request_id_str);
96                 if (!g_hash_table_size(http_reqid_hash)) {
97                         g_hash_table_destroy(http_reqid_hash);
98                         http_reqid_hash = NULL;
99                 }
100         }
101         if (request_id_str) {
102                 g_free(request_id_str);
103         }
104
105         if (recv_data) {
106                 g_free(recv_data);
107         }
108         if (poi_list) {
109                 decarta_poi_list_free (poi_list);
110         }
111         if (req_id_str) {
112                 g_free(req_id_str);
113         }
114         if (error_code) {
115                 g_free(error_code);
116         }
117         if (error_msg) {
118                 g_free(error_msg);
119         }
120         if (cb_data) {
121                 g_free(cb_data);
122         }
123 }
124
125 EXPORT_API int
126 decarta_search_directory (const DecartaDirectoryRequest *dir_request,
127         GList **poi_list)
128 {
129         DECARTA_LOGD("decarta_search_directory");
130         if (!dir_request || !poi_list)   return DECARTA_ERROR_PARAMETER;
131         if (!load_config()) return DECARTA_ERROR_CONFIGURATION_FILE;
132
133         int err = DECARTA_ERROR_NONE;
134         char *req = NULL;
135         char *resp = NULL;
136         unsigned int size = 0;
137         gchar *req_id_str = NULL;
138         gchar *error_code = NULL;
139         gchar *error_msg = NULL;
140         if (!xml_directory_request_get(dir_request, &req, &size)) return DECARTA_ERROR_PARAMETER;
141         HttpHandle http = http_open(HTTP_TYPE_SYNC);
142         if (http_send(http, req, get_host(), &resp, NULL, NULL)) {
143                 if (!xml_directory_parse(resp, poi_list, &req_id_str, &error_code, &error_msg)) err = DECARTA_ERROR_XML;
144         } else err = DECARTA_ERROR_HTTP;
145
146         DECARTA_LOGD("decarta_search_directory: req_id %s, error_code %s, error_msg %s", req_id_str, error_code, error_msg);
147         if (req_id_str) {
148                 g_free(req_id_str);
149         }
150         if (error_code) {
151                 g_free(error_code);
152         }
153         if (error_msg) {
154                 g_free(error_msg);
155         }
156         if (req) {
157                 g_free (req);
158         }
159         if (resp) {
160                 g_free (resp);
161         }
162         http_close(http);
163         return err;
164 }
165
166 EXPORT_API int
167 decarta_search_directory_async (const DecartaDirectoryRequest *dir_request,
168         DecartaDirectoryCB callback,
169         void *userdata)
170 {
171         DECARTA_LOGD("decarta_search_directory_async");
172         if (!dir_request || !callback) return DECARTA_ERROR_PARAMETER;
173         if (!load_config()) return DECARTA_ERROR_CONFIGURATION_FILE;
174
175         char* req = NULL;
176         unsigned int size = 0;
177         DecartaDirCBData* cb_data = g_new0(DecartaDirCBData, 1);
178         cb_data->callback = callback;
179         cb_data->userdata = userdata;
180         cb_data->request_id = dir_request->request_id;
181
182         if(!xml_directory_request_get(dir_request, &req, &size)) {
183                 if (cb_data) {
184                         g_free(cb_data);
185                         cb_data  = NULL;
186                 }
187                 if (req) {
188                         g_free(req);
189                 }
190                 return DECARTA_ERROR_PARAMETER;
191         }
192
193         char *request_id_str = g_strdup_printf("%u", dir_request->request_id);
194         if (request_id_str == NULL) {
195                 if (cb_data) {
196                         g_free(cb_data);
197                         cb_data = NULL;
198                 }
199                 if (req) {
200                         g_free(req);
201                 }
202                 return DECARTA_ERROR_PARAMETER;
203         }
204
205         HttpHandle http_async = http_open(HTTP_TYPE_ASYNC);
206         DECARTA_LOGD("decarta_search_directory_async: http %d, req_id %d", http_async, dir_request->request_id);
207         if (!http_reqid_hash) {
208                 http_reqid_hash = g_hash_table_new(g_str_hash, g_str_equal);
209                 if (http_reqid_hash == NULL) {
210                         if (request_id_str) {
211                                 g_free(request_id_str);
212                         }
213                         if (cb_data) {
214                                 g_free(cb_data);
215                                 cb_data = NULL;
216                         }
217                         if (req) {
218                                 g_free(req);
219                         }
220                         http_close(http_async);
221                         return DECARTA_ERROR_HTTP;
222                 }
223                 g_hash_table_insert(http_reqid_hash, (gpointer)request_id_str, (gpointer)http_async);
224                 DECARTA_LOGD("first insert http [0x%x], req_id [%d]", http_async, dir_request->request_id);
225         } else {
226                 g_hash_table_insert(http_reqid_hash, (gpointer)request_id_str, (gpointer)http_async);
227                 DECARTA_LOGD("Not the first insert http [0x%x], req_id [%d]", http_async, dir_request->request_id);
228         }
229
230         if(!http_send(http_async, req, get_host(), NULL, (HttpCallback)search_directory_cb, cb_data)){
231                 g_hash_table_foreach_remove(http_reqid_hash, (GHRFunc)__directory_del_table_node_cb, (gpointer)request_id_str);
232                 if (!g_hash_table_size(http_reqid_hash)) {
233                         g_hash_table_destroy(http_reqid_hash);
234                         http_reqid_hash = NULL;
235                 }
236
237                 if (cb_data) {
238                         g_free(cb_data);
239                         cb_data = NULL;
240                 }
241                 if (req) {
242                         g_free(req);
243                 }
244                 return DECARTA_ERROR_HTTP;
245         }
246
247         // cb_data will be freed in callback
248         if (req) {
249                 g_free(req);
250         }
251         return DECARTA_ERROR_NONE;
252 }
253
254 EXPORT_API void
255 decarta_search_directory_async_cancel (guint request_id)
256 {
257         DECARTA_LOGD("decarta_search_directory_async_cancel: req_id %d called", request_id);
258
259         if (http_reqid_hash) {
260                 char *request_id_str = g_strdup_printf("%u", request_id);
261                 if (request_id_str == NULL) {
262                         return;
263                 }
264
265                 /** cancel the request_id http async request*/
266                 g_hash_table_foreach_remove(http_reqid_hash, (GHRFunc)__directory_del_table_node_cb, (gpointer)request_id_str);
267                 g_free(request_id_str);
268         } else {
269                 DECARTA_LOGD("decarta_search_directory_async_cancel: req_id %d http_reqid_hash NOT exist!", request_id);
270         }
271 }