Fix a crash
[framework/location/libdecarta.git] / decarta / decarta_maps.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
28 #include "decarta_log.h"
29 #include "decarta_config.h"
30 #include "http_wrapper.h"
31 #include "decarta_xml.h"
32 #include "decarta_maps.h"
33
34 typedef struct {
35         DecartaMapCB callback;
36         void *userdata;
37         guint request_id; /**< used to remove from table after success */
38 } DecartaMapCBData;
39
40 static GHashTable *http_reqid_hash = NULL;
41 static guint request_id = 1;
42
43 static gboolean
44 __maps_del_table_node_cb(gpointer key,
45         gpointer value,
46         gpointer user_data)
47 {
48         if (!user_data || !key || !value) {
49                 return false;
50         }
51         HttpHandle http_async = NULL;
52
53         http_async = (HttpHandle)value;
54         char *user_key = (char *)user_data;
55         char *table_key = (char *)key;
56
57         if (!g_strcmp0(user_key, table_key)) {
58                 DECARTA_LOGD("req_id [%s] http_async [%d] closed!", table_key, http_async);
59                 g_free(table_key);
60                 http_close(http_async);
61                 return true;
62         }
63         DECARTA_LOGD("req_id [%s] http_async [%d] not close", table_key, http_async);
64         return false;
65 }
66
67 static gboolean
68 __maps_del_table_all_cb(gpointer key,
69         gpointer value,
70         gpointer user_data)
71 {
72         if (!key || !value) {
73                 return false;
74         }
75
76         HttpHandle http_async = NULL;
77         http_async = (HttpHandle)value;
78         char *table_key = (char *)key;
79
80         DECARTA_LOGD("req_id [%s] http_async [%d] closed!", table_key, http_async);
81         g_free(table_key);
82         http_close(http_async);
83         return true;
84 }
85
86 static void
87 http_map_cb (gboolean success,
88         char *recv_data,
89         void *userdata)
90 {
91         DECARTA_LOGD("map_cb");
92         DecartaMapCBData* cb_data = (DecartaMapCBData*)userdata;
93         DecartaError err = DECARTA_ERROR_NONE;
94         DecartaMap *map = NULL;
95         if (success != TRUE) err = DECARTA_ERROR_HTTP;
96         else if (!xml_map_parse (recv_data, &map)) err = DECARTA_ERROR_XML;
97         if (cb_data->callback) cb_data->callback (err, map, cb_data->userdata);
98
99         /** remove the success request id from hash table */
100         char *request_id_str = g_strdup_printf("%u", cb_data->request_id);
101         if (http_reqid_hash) {
102                 DECARTA_LOGD("remove the http async after success!");
103                 g_hash_table_foreach_remove(http_reqid_hash, (GHRFunc)__maps_del_table_node_cb, (gpointer)request_id_str);
104                 if (!g_hash_table_size(http_reqid_hash)) {
105                         g_hash_table_destroy(http_reqid_hash);
106                         http_reqid_hash = NULL;
107                 }
108         }
109         if (request_id_str) {
110                 g_free(request_id_str);
111         }
112
113         g_free(recv_data);
114         if (map) decarta_map_free (map);
115         g_free(cb_data);
116 }
117
118 EXPORT_API int
119 decarta_search_map (const DecartaPosition *pos,
120         int zoom,
121         DecartaMap **map)
122 {
123         DECARTA_LOGD("decarta_search_geocode");
124         if (!pos || !map)   return DECARTA_ERROR_PARAMETER;
125         if (!load_config()) return DECARTA_ERROR_CONFIGURATION_FILE;
126
127         int err = DECARTA_ERROR_NONE;
128         char *req = NULL;
129         char *resp = NULL;
130         unsigned int size = 0;
131         if (!xml_map_request_get(pos, zoom, &req, &size)) return DECARTA_ERROR_PARAMETER;
132         HttpHandle http = http_open(HTTP_TYPE_SYNC);
133         if (http_send(http, req, get_host(), &resp, NULL, NULL)) {
134
135                 if (!xml_map_parse (resp, map)) err = DECARTA_ERROR_XML;
136                 //if( 0 != process_tile_grid(resp, map)) err = DECARTA_ERROR_XML;
137
138         } else err = DECARTA_ERROR_HTTP;
139         g_free (req);
140         g_free (resp);
141         http_close(http);
142         return err;
143 }
144
145 EXPORT_API int
146 decarta_search_map_async (const DecartaPosition *pos,
147         int zoom,
148         DecartaMapCB callback,
149         void *userdata)
150 {
151         DECARTA_LOGD("decarta_search_map_async");
152         if (!pos || !callback) return DECARTA_ERROR_PARAMETER;
153         if (!load_config()) return DECARTA_ERROR_CONFIGURATION_FILE;
154
155         char* req = NULL;
156         unsigned int size = 0;
157         DecartaMapCBData* cb_data = g_new0(DecartaMapCBData, 1);
158         cb_data->callback = callback;
159         cb_data->userdata = userdata;
160         request_id++;
161         cb_data->request_id = request_id;
162
163         if (!xml_map_request_get(pos, zoom, &req, &size)) {
164                 if (cb_data) {
165                         g_free(cb_data);
166                         cb_data = NULL;
167                 }
168                 if (req) {
169                         g_free(req);
170                 }
171                 return DECARTA_ERROR_PARAMETER;
172         }
173
174         char *request_id_str = g_strdup_printf("%u", request_id);
175         if (request_id_str == NULL) {
176                 if (cb_data) {
177                         g_free(cb_data);
178                         cb_data = NULL;
179                 }
180                 if (req) {
181                         g_free(req);
182                 }
183                 return DECARTA_ERROR_PARAMETER;
184         }
185
186         HttpHandle http_async = http_open(HTTP_TYPE_ASYNC);
187
188         if (!http_reqid_hash) {
189                 http_reqid_hash = g_hash_table_new(g_str_hash, g_str_equal);
190                 if (http_reqid_hash == NULL) {
191                         if (request_id_str) {
192                                 g_free(request_id_str);
193                         }
194                         if (cb_data) {
195                                 g_free(cb_data);
196                                 cb_data = NULL;
197                         }
198                         if (req) {
199                                 g_free(req);
200                         }
201                         http_close(http_async);
202                         return DECARTA_ERROR_HTTP;
203                 }
204                 g_hash_table_insert(http_reqid_hash, (gpointer)request_id_str, (gpointer)http_async);
205                 DECARTA_LOGD("first insert http [0x%x], req_id [%d]", http_async, request_id);
206         } else {
207                 g_hash_table_insert(http_reqid_hash, (gpointer)request_id_str, (gpointer)http_async);
208                 DECARTA_LOGD("Not the first insert http [0x%x], req_id [%d]", http_async, request_id);
209         }
210
211         if(!http_send(http_async, req, get_host(), NULL, (HttpCallback)http_map_cb, cb_data)){
212                 g_hash_table_foreach_remove(http_reqid_hash, (GHRFunc)__maps_del_table_node_cb, (gpointer)request_id_str);
213                 if (!g_hash_table_size(http_reqid_hash)) {
214                         g_hash_table_destroy(http_reqid_hash);
215                         http_reqid_hash = NULL;
216                 }
217                 if (cb_data) {
218                         g_free(cb_data);
219                         cb_data = NULL;
220                 }
221                 if (req) {
222                         g_free(req);
223                 }
224                 return DECARTA_ERROR_HTTP;
225         }
226
227         if (req) {
228                 g_free(req);
229         }
230
231         return DECARTA_ERROR_NONE;
232 }
233
234 EXPORT_API void
235 decarta_search_map_async_cancel (void)
236 {
237         if (http_reqid_hash) {
238                 /** cancel the all rest mapping http async requests*/
239                 g_hash_table_foreach_remove(http_reqid_hash, (GHRFunc)__maps_del_table_all_cb, NULL);
240         } else {
241                 DECARTA_LOGD("decarta_search_map_async_cancel: http_reqid_hash NOT exist!");
242         }
243 }