Fix a crash
[framework/location/libdecarta.git] / decarta / http_wrapper.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 <gconf/gconf-client.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <libsoup/soup.h>
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "decarta_log.h"
33 #include "http_wrapper.h"
34
35 #define GCONF_HTTP_PROXY_HOST     "/system/http_proxy/host"
36 #define GCONF_HTTP_PROXY_PORT     "/system/http_proxy/port"
37
38 #define DECARTA_NUM_HTTP_CONNECTIONS    128
39
40 typedef struct {
41         HttpType type;
42         SoupSession* session;
43 } HttpWrapper;
44
45 static char* get_proxy()
46 {
47         char *host = NULL;
48         int port;
49         char* proxy_string = NULL;
50
51 #if 0 //We should check why the previous member use gconf
52         GConfClient* gconf_client = gconf_client_get_default();
53         if(gconf_client == NULL)
54                 return NULL;
55
56         host = gconf_client_get_string(gconf_client, GCONF_HTTP_PROXY_HOST, NULL);
57         if( host && *host){
58                 port = gconf_client_get_int(gconf_client, GCONF_HTTP_PROXY_PORT, NULL);
59                 if(port)
60                         proxy_string = g_strdup_printf("http://%s:%u", host, port);
61                 else
62                         proxy_string = g_strdup_printf("http://%s", host);
63         }
64
65         g_free(host);
66         g_object_unref(gconf_client);
67 #else
68
69         host = getenv("http_proxy");
70         if (host == NULL)
71                 return NULL;
72
73         if (strncmp(host, "http://", 7)) {
74                 proxy_string = g_strdup_printf("http://%s", host);
75         } else {
76                 proxy_string = g_strdup_printf("%s", host);
77         }
78 #endif
79
80         return proxy_string;
81 }
82
83 static SoupSession* soup_create_session_async()
84 {
85         SoupSession* session = NULL;
86         char* proxy_string = get_proxy();
87         if (proxy_string == NULL){
88                 DECARTA_LOGD("\tNo proxy");
89                 session = soup_session_async_new_with_options (
90                                 SOUP_SESSION_MAX_CONNS, DECARTA_NUM_HTTP_CONNECTIONS,
91                                 SOUP_SESSION_MAX_CONNS_PER_HOST, DECARTA_NUM_HTTP_CONNECTIONS, NULL);
92         }else{
93                 DECARTA_LOGD("\tProxy readed [%s]", proxy_string);
94                 SoupURI* uri = soup_uri_new(proxy_string);
95                 session = soup_session_async_new_with_options (
96                                 SOUP_SESSION_PROXY_URI, uri,
97                                 SOUP_SESSION_MAX_CONNS, DECARTA_NUM_HTTP_CONNECTIONS,
98                                 SOUP_SESSION_MAX_CONNS_PER_HOST, DECARTA_NUM_HTTP_CONNECTIONS, NULL);
99                 g_free(proxy_string);
100                 soup_uri_free(uri);
101         }
102         return session;
103 }
104
105
106 static SoupSession* soup_create_session()
107 {
108         SoupSession* session = NULL;
109         char* proxy_string = get_proxy();
110         if (proxy_string == NULL){
111                 DECARTA_LOGD("\tNo proxy");
112                 session = soup_session_sync_new_with_options (
113                                 SOUP_SESSION_MAX_CONNS, DECARTA_NUM_HTTP_CONNECTIONS,
114                                 SOUP_SESSION_MAX_CONNS_PER_HOST, DECARTA_NUM_HTTP_CONNECTIONS, NULL);
115         }else{
116                 DECARTA_LOGD("\tProxy readed [%s]", proxy_string);
117                 SoupURI* uri = soup_uri_new(proxy_string);
118                 session = soup_session_sync_new_with_options (
119                                 SOUP_SESSION_PROXY_URI, uri,
120                                 SOUP_SESSION_MAX_CONNS, DECARTA_NUM_HTTP_CONNECTIONS,
121                                 SOUP_SESSION_MAX_CONNS_PER_HOST, DECARTA_NUM_HTTP_CONNECTIONS, NULL);
122                 g_free(proxy_string);
123                 soup_uri_free(uri);
124         }
125         return session;
126 }
127
128
129 static void soup_delete_session(SoupSession* session)
130 {
131         if (session) {
132                 g_object_unref (session);
133                 DECARTA_LOGD("\tSoup session removed");
134         }else
135                 DECARTA_LOGW("\tSoup session already removed");
136 }
137
138 static SoupMessage* soup_create_msg(const char* send_data, int send_data_size, const char* host)
139 {
140         if(!send_data || !host){
141                 DECARTA_LOGW("http or Sending data or host is NULL");
142                 return NULL;
143         }
144
145         SoupMessage* msg = soup_message_new (SOUP_METHOD_POST, host);
146         if (!msg){
147                 DECARTA_LOGW("Soup message creation failed");
148                 return NULL;
149         }
150         soup_message_set_request(msg, "text/xml", SOUP_MEMORY_COPY, send_data, send_data_size);
151         soup_message_headers_append(msg->request_headers, "Content-Type", "text/xml");
152
153         return msg;
154 }
155
156 static void soup_delete_msg(SoupMessage* msg)
157 {
158         if(msg){
159                 g_object_unref(msg);
160         }
161 }
162
163 static char* soup_msg_process(SoupMessage* msg)
164 {
165         char* recv_data = NULL;
166         if(msg == NULL){
167                 DECARTA_LOGD("\tSoup message is NULL");
168                 return NULL;
169         }
170         if(msg->status_code != SOUP_STATUS_OK){
171                 DECARTA_LOGD("http response error [%d, %s]", msg->status_code, msg->reason_phrase);
172                 return NULL;
173         }
174         recv_data = g_new0(char, msg->response_body->length + 1);
175         g_memmove(recv_data, msg->response_body->data, msg->response_body->length);
176         recv_data[msg->response_body->length] = 0;
177         return recv_data;
178 }
179
180 typedef struct{
181         HttpCallback callback;
182         void* user_data;
183 } HttpCBData;
184
185 static void soup_callback(SoupSession * session, SoupMessage * msg, HttpCBData* http_cb_data)
186 {
187         if(!session || !msg){
188                 DECARTA_LOGD("\thttp session or msg is NULL");
189                 if(http_cb_data && http_cb_data->callback)
190                         http_cb_data->callback(FALSE, NULL, http_cb_data->user_data);
191                 return;
192         }
193
194         DECARTA_LOGD ("\tResponse[%d, %s]", msg->status_code, msg->reason_phrase);
195
196         if (msg->status_code == SOUP_STATUS_CANCELLED) {
197                 DECARTA_LOGD("http response cancelled");
198                 return;
199         }
200         if(msg->status_code != SOUP_STATUS_OK){
201                 DECARTA_LOGD("http response error [%d]", msg->status_code);
202                 http_cb_data->callback(FALSE, NULL, http_cb_data->user_data);
203                 return;
204         }
205         char* recv_data = g_new0(char, msg->response_body->length + 1);
206         g_memmove(recv_data, msg->response_body->data, msg->response_body->length);
207         recv_data[msg->response_body->length] = 0;
208         http_cb_data->callback(TRUE, recv_data, http_cb_data->user_data);
209         g_free(http_cb_data);
210 }
211
212 gboolean http_send(HttpHandle handle, const char* send_data, const char* host, char** recv_data, HttpCallback cb, void* user_data)
213 {
214         DECARTA_LOGD ("http_send: %s", host);
215         HttpWrapper* http = (HttpWrapper*)handle;
216         if(!http || !http->session|| !send_data || !host){
217                 DECARTA_LOGW("http or soup session or sending data or host or callback is NULL or http type is not sync");
218                 return FALSE;
219         }
220         int send_data_size = strlen(send_data);
221         SoupMessage* msg = soup_create_msg(send_data, send_data_size, host);
222         if(!msg)
223                 return FALSE;
224
225         int ret = FALSE;
226         switch(http->type)
227         {
228                 case HTTP_TYPE_SYNC:{
229                         soup_session_send_message(http->session, msg);
230                         char* soup_recv_data = soup_msg_process(msg);
231                         soup_delete_msg(msg);
232                         if( soup_recv_data && recv_data){
233                                 *recv_data = g_memdup(soup_recv_data, strlen(soup_recv_data));
234                                 ret = TRUE;
235                         }
236                         g_free(soup_recv_data);
237                         break;
238                 }
239                 case HTTP_TYPE_ASYNC:{
240                         if(cb){
241                                 HttpCBData* http_cb_data = g_new0(HttpCBData, 1);
242                                 http_cb_data->callback = cb;
243                                 http_cb_data->user_data = user_data;
244                                 soup_session_queue_message (http->session, msg, (SoupSessionCallback)soup_callback, http_cb_data);
245                                 ret = TRUE;
246                         }
247                         break;
248                 }
249                 default:
250                         DECARTA_LOGD("Undefined http type");
251
252         }
253         return ret;
254 }
255
256 gboolean http_abort(HttpHandle handle)
257 {
258         HttpWrapper* http = (HttpWrapper*)handle;
259         if(http->session)
260                 soup_session_abort (http->session);
261
262         return TRUE;
263 }
264
265 HttpHandle http_open (HttpType type)
266 {
267         g_type_init();
268
269         HttpWrapper* http = g_new0(HttpWrapper, 1);
270         http->type = type;
271         http->session = NULL;
272         switch(http->type)
273         {
274                 case HTTP_TYPE_SYNC:{
275                         http->session = soup_create_session();
276                         break;
277                 }
278                 case HTTP_TYPE_ASYNC:{
279                         http->session = soup_create_session_async();
280                         break;
281                 }
282                 default:
283                         DECARTA_LOGW("\tError: undefined http type");
284                         http->session = NULL;
285         }
286
287         if(!http->session){
288                 g_free(http);
289                 http = NULL;
290         }
291         return http;
292 }
293
294 void http_close (HttpHandle handle)
295 {
296         HttpWrapper* http = (HttpWrapper*)handle;
297         if(!http){
298                 DECARTA_LOGW("http is NULL");
299                 return;
300         }
301         http_abort(http);
302         soup_delete_session(http->session);
303 }