4 * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Youngae Kang <youngae.kang@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
7 * Genie Kim <daejins.kim@samsung.com>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <curl/curl.h>
29 #include "location-osm-route.h"
32 //http://www.yournavigation.org/api/1.0/gosmore.php?format=geojson&flat=52.215676&flon=5.963946&tlat=52.2573&tlon=6.1799&v=motorcar&fast=1&layer=mapnik
35 #define YOUR_NAVIGATION_SERVER "http://www.yournavigation.org/api/1.0/gosmore.php?"
36 #define YOUR_NAVIGATION_FORMAT "format="
38 #define KML_FORMAT "kml"
39 #define GEOJSON_FORMAT "geojson"
41 static CURLM *g_multi_handle;
42 static pthread_t g_http_thread;
43 static GHashTable *g_req_table;
45 pthread_mutex_t curl_mutex = PTHREAD_MUTEX_INITIALIZER;
47 typedef int (*curl_async_cb) (int req_id, int error, const char *result, int result_len, void *user_data);
60 curl_create_session (guint *req_id)
62 static guint session_id = 0;
64 CURL_MUTEX_LOCK(&curl_mutex);
66 g_multi_handle = curl_multi_init();
67 CURL_MUTEX_UNLOCK(&curl_mutex);
69 CURL* ctx = curl_easy_init();
71 MOD_LOGW("Unable to initialize cURL interface\n");
75 *req_id = ++session_id;
77 MOD_LOGW ("req_id [%d]", *req_id);
83 curl_destroy_session (CURL* ctx)
87 curl_easy_cleanup(ctx);
93 _compare_ctx (gpointer key, gpointer value, gpointer userdata)
95 if (!key || !value || !userdata) return FALSE;
97 curl_item_t * item = (curl_item_t*) value;
98 CURL *ctx = (CURL*) userdata;
100 if (item->ctx == ctx) {
108 _send_resp (curl_item_t *item)
110 MOD_LOGW ("Send response [%p]", item);
111 if (!item) return -1;
112 MOD_LOGW("Result [%s]", item->result);
115 item->cb (item->req_id, 0, item->result, item->result_len, item->user_data);
117 if (item->user_data) {
118 g_free(item->user_data);
119 item->user_data = NULL;
123 g_free(item->result);
131 _create_http_thread(void *data)
133 MOD_LOGW ("Create Thread");
136 int still_running = 1;
139 struct timeval timeout;
144 while(still_running) {
155 curl_multi_fdset (g_multi_handle, &fdread, &fdwrite, &fdexecp, &maxfd);
157 MOD_LOGW ("Hash table is NULL");
161 rc = select(maxfd+1, &fdread, &fdwrite, &fdexecp, &timeout);
162 MOD_LOGW ("run loop [%d]", still_running);
168 /* Timeout or readable / writable sockets */
169 curl_multi_perform(g_multi_handle, &still_running);
170 if (ret != CURLM_OK) {
171 MOD_LOGW ("curl_multi_perform error [%d]", ret);
175 msg = curl_multi_info_read(g_multi_handle, &msgs_left);
176 if (msg && msg->msg == CURLMSG_DONE) {
177 curl_item_t *item = g_hash_table_find (g_req_table, _compare_ctx, msg->easy_handle);
179 MOD_LOGW ("Found Item ID[%d]", item->req_id);
180 int ret = _send_resp(item);
182 MOD_LOGW ("Fail to send response [%d]", ret);
187 g_hash_table_remove (g_req_table, (gpointer) &item->req_id);
189 curl_destroy_session(item->ctx);
204 CURL_MUTEX_LOCK (&curl_mutex);
205 if (g_multi_handle) {
206 curl_multi_cleanup(g_multi_handle);
207 g_multi_handle = NULL;
209 CURL_MUTEX_UNLOCK (&curl_mutex);
211 MOD_LOGW("End Thread");
218 _osm_route_cb (char *ptr, size_t size, size_t nmemb, void *userdata)
220 curl_item_t *item = (curl_item_t*)userdata;
222 MOD_LOGW("size[%d], nmemb [%d]", size, nmemb);
223 int reallo_len = size * nmemb;
225 item->result = realloc (item->result, item->result_len + reallo_len + 1);
226 if (item->result == NULL) {
228 MOD_LOGW("not enough memory (realloc returned NULL)\n");
232 memcpy(&(item->result[item->result_len]), ptr, reallo_len);
233 item->result_len += reallo_len;
234 item->result[item->result_len] = 0;
240 _route_cb (int req_id, int error, const char *result, int result_len, void *user_data)
243 char *error_code = NULL;
244 char *error_msg = NULL;
246 osm_data_t *ndata = (osm_data_t *) user_data;
247 if (result && result_len > 0) {
251 convert_data_to_location_service (result, result_len, ndata->origin, ndata->dest, &route);
254 ndata->route_cb(error, req_id, route, error_code, error_msg, ndata->user_data);
260 curl_request_route_async(const char *url, osm_data_t *data, guint *req_id)
262 curl_item_t *item = g_new0(curl_item_t, 1);
263 if (!item) return -999;
265 int stillrunning = 0;
268 CURL *ctx = curl_create_session (req_id);
278 item->req_id = *req_id;
279 item->user_data = data;
281 item->cb = _route_cb;
283 curl_easy_setopt (ctx, CURLOPT_URL, url);
284 // curl_easy_setopt (ctx, CURLOPT_NOPROGRESS , 0L);
285 // curl_easy_setopt( ctx , CURLOPT_WRITEHEADER , stderr);
286 curl_easy_setopt( ctx, CURLOPT_WRITEFUNCTION, _osm_route_cb);
287 curl_easy_setopt( ctx , CURLOPT_WRITEDATA, item);
289 CURL_MUTEX_LOCK (&curl_mutex);
290 curl_multi_add_handle(g_multi_handle, ctx);
293 g_req_table = g_hash_table_new (g_int_hash, g_int_equal);
296 g_hash_table_insert(g_req_table, req_id, item);
298 MOD_LOGW ("ReqID: %u", *req_id);
300 err = curl_multi_perform(g_multi_handle, &stillrunning);
301 CURL_MUTEX_UNLOCK (&curl_mutex);
302 if (CURLM_OK != err) {
303 MOD_LOGW ("curl_multi_perform error[%d]", err);
309 curl_destroy_session(ctx);
313 if (!g_http_thread) { //TODO
314 ret = pthread_create(&g_http_thread, NULL, _create_http_thread, NULL);
318 MOD_LOGW ("Fail to create thread [%d", ret);
324 curl_destroy_session(ctx);
327 MOD_LOGW ("End loop");
328 pthread_detach(g_http_thread);
331 MOD_LOGW ("Thread is alive");
338 curl_cancel_route_request (guint req_id)
340 curl_item_t* item = NULL;
343 return LOCATION_ERROR_NOT_FOUND;
346 item = (curl_item_t *)g_hash_table_lookup (g_req_table, (void* )&req_id);
348 return LOCATION_ERROR_NOT_FOUND;
352 if (g_multi_handle) {
353 curl_multi_remove_handle (g_multi_handle, item->ctx);
356 if( item->user_data) {
357 g_free (item->user_data);
358 item->user_data = NULL;
362 g_free (item->result);
370 gboolean ret = g_hash_table_remove(g_req_table, (void *)&req_id);
372 return LOCATION_ERROR_NOT_FOUND;
374 if (g_hash_table_size(g_req_table) == 0) {
375 MOD_LOGW ("Hash table is NULL");
376 g_hash_table_destroy(g_req_table);
380 return LOCATION_ERROR_NONE;