Ticket #130: libsyncml-libsoup24.diff
| File libsyncml-libsoup24.diff, 17.4 kB (added by danw, 10 months ago) |
|---|
-
libsyncml/transports/http_client_internals.h
old new 25 25 #include <libsoup/soup-uri.h> 26 26 27 27 typedef struct SmlTransportHttpClientEnv { 28 #ifdef HAVE_LIBSOUP22 28 29 SoupUri *uri; 30 #else 31 SoupURI *uri; 32 #endif 29 33 SoupSession *session; 30 34 SmlTransport *tsp; 31 35 uint16_t port; … … 35 39 char *username; 36 40 char *password; 37 41 SmlBool connectDone; 38 GMutex *cleanupMutex;39 SmlBool shutdown;40 42 } SmlTransportHttpClientEnv; 41 43 42 44 #endif //_HTTP_CLIENT_INTERNALS_H_ -
libsyncml/transports/http_client.c
old new 38 38 */ 39 39 /*@{*/ 40 40 41 #ifdef HAVE_LIBSOUP22 42 #define soup_message_headers_get soup_message_get_header 43 #define soup_message_headers_append soup_message_add_header 44 #endif 45 46 #ifdef HAVE_LIBSOUP22 41 47 static void _msgReceived(SoupMessage *msg, gpointer userdata) 48 #else 49 static void _msgReceived(SoupSession *session, SoupMessage *msg, gpointer userdata) 50 #endif 42 51 { 43 52 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, msg, userdata); 44 53 SmlTransportHttpClientEnv *env = userdata; 45 54 SmlError *error = NULL; 46 55 47 /* this mutex lock is necessary to avoid conflicts with session shutdown */48 g_mutex_lock(env->cleanupMutex);49 50 56 /* handle potential session shutdown */ 51 if ( env->shutdown)57 if (msg->status_code == SOUP_STATUS_CANCELLED) 52 58 { 53 /* a call to finalize failed because of libsoup 54 * so try to finalize again and ignore the message 55 */ 56 g_mutex_unlock(env->cleanupMutex); 57 smlTrace(TRACE_INTERNAL, "%s - failed finalize detected", __func__); 58 smlTransportHttpClientFinalize(userdata, NULL); 59 smlTrace(TRACE_INTERNAL, "%s - ignoring due to shutdown", __func__); 59 60 smlTrace(TRACE_EXIT, "%s", __func__); 60 61 return; 61 62 } … … 101 102 } 102 103 103 104 /* check the header of the received message */ 104 const char *header = soup_message_ get_header(msg->response_headers, "Content-Type");105 const char *header = soup_message_headers_get(msg->response_headers, "Content-Type"); 105 106 smlTrace(TRACE_INTERNAL, "content type: %s", header); 106 107 107 108 SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN; … … 121 122 } 122 123 123 124 /* prepare the received message */ 124 char *data = smlTryMalloc0(msg->response.length, &error); 125 char *data; 126 gsize length; 127 128 #ifdef HAVE_LIBSOUP22 129 length = msg->response.length; 130 #else 131 length = msg->response_body->length; 132 #endif 133 134 data = smlTryMalloc0(length, &error); 125 135 if (!data) 126 136 goto error; 127 memcpy(data, msg->response.body, msg->response.length); 128 129 SmlTransportData *tspdata = smlTransportDataNew(data, msg->response.length, mimetype, TRUE, &error); 137 138 #ifdef HAVE_LIBSOUP22 139 memcpy(data, msg->response.body, length); 140 #else 141 memcpy(data, msg->response_body->data, length); 142 #endif 143 144 SmlTransportData *tspdata = smlTransportDataNew(data, length, mimetype, TRUE, &error); 130 145 if (!tspdata) 131 146 goto error_free_data; 132 147 … … 135 150 136 151 /* cleanup */ 137 152 smlTransportDataDeref(tspdata); 138 g_mutex_unlock(env->cleanupMutex);139 153 140 154 smlTrace(TRACE_EXIT, "%s", __func__); 141 155 return; … … 144 158 g_free(data); 145 159 error: 146 160 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error); 147 g_mutex_unlock(env->cleanupMutex);148 161 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); 149 162 smlErrorDeref(&error); 150 163 } … … 156 169 * account. Usually this is not required because the most 157 170 * SyncML server manage the authentication via SyncHdr. 158 171 */ 172 173 #ifdef HAVE_LIBSOUP22 159 174 static void 160 175 _authenticate (SoupSession *session, SoupMessage *msg, 161 176 const char *auth_type, const char *auth_realm, … … 166 181 *username = g_strdup(env->username); 167 182 *password = g_strdup(env->password); 168 183 } 184 #else 185 static void 186 _authenticate (SoupSession *session, SoupMessage *msg, 187 SoupAuth *auth, gboolean retrying, gpointer data) 188 { 189 SmlTransportHttpClientEnv *env = data; 190 smlTrace(TRACE_INTERNAL, "%s: authentication via auth_type %s", __func__, soup_auth_get_scheme_name (auth)); 169 191 192 if (!retrying) 193 soup_auth_authenticate(auth, env->username, env->password); 194 } 195 #endif 196 170 197 /*@}*/ 171 198 172 199 /** … … 202 229 env->url = g_strdup(config->url); 203 230 env->proxy = g_strdup(config->proxy); 204 231 env->connectDone = FALSE; 205 env->cleanupMutex = g_mutex_new();206 env->shutdown = FALSE;207 232 208 233 env->tsp = tsp; 209 234 if (config->proxy != NULL && strlen(config->proxy) > 0 || … … 253 278 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error); 254 279 smlAssert(data); 255 280 SmlTransportHttpClientEnv *env = data; 256 g_mutex_lock(env->cleanupMutex);257 281 258 282 smlAssert(env->tsp); 259 283 260 env->shutdown = TRUE; 261 262 // try to stop the session 263 // this is a really nasty thing with lipsoup 264 if (!soup_session_try_prune_connection(env->session)) 265 { 266 // do not touch the env because otherwise _msgReceived can produce crashs 267 // do not signal this as an error because this memory leak is not fixable 268 // if you know what to do then feel free to correct me :) 269 smlTrace(TRACE_EXIT_ERROR, "%s - connection was not pruned", __func__); 270 g_mutex_unlock(env->cleanupMutex); 271 return TRUE; 272 } 284 soup_session_abort(env->session); 273 285 g_object_unref(env->session); 274 286 env->session = NULL; 275 287 276 // if we are here then there are definitely no actions on the road277 // from libsoup session. so it is safe to give up control and cleanup278 g_mutex_unlock(env->cleanupMutex);279 g_mutex_free(env->cleanupMutex);280 281 288 if (env->data != NULL) 282 289 { 283 290 smlTransportDataDeref(env->data); … … 312 319 goto error; 313 320 } 314 321 322 const char *content_type; 315 323 switch (data->type) { 316 324 case SML_MIMETYPE_XML: 317 soup_message_add_header(msg->request_headers, "Content-Type", SML_ELEMENT_XML); 318 soup_message_add_header(msg->request_headers, "Accept", SML_ELEMENT_XML); 325 content_type = SML_ELEMENT_XML; 319 326 break; 320 327 case SML_MIMETYPE_WBXML: 321 soup_message_add_header(msg->request_headers, "Content-Type", SML_ELEMENT_WBXML); 322 soup_message_add_header(msg->request_headers, "Accept", SML_ELEMENT_WBXML); 328 content_type = SML_ELEMENT_WBXML; 323 329 break; 324 330 case SML_MIMETYPE_SAN: 325 soup_message_add_header(msg->request_headers, "Content-Type", SML_ELEMENT_SAN); 326 soup_message_add_header(msg->request_headers, "Accept", SML_ELEMENT_SAN); 331 content_type = SML_ELEMENT_SAN; 327 332 default: 328 333 smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown Mimetype %d", data->type); 329 334 goto error_free_message; 330 335 } 331 336 332 msg->request.body = data->data; 333 msg->request.length = data->size; 334 msg->request.owner = SOUP_BUFFER_USER_OWNED; 337 soup_message_headers_append(msg->request_headers, "Accept", content_type); 338 soup_message_set_request (msg, content_type, 339 #ifdef HAVE_LIBSOUP22 340 SOUP_BUFFER_USER_OWNED, 341 #else 342 SOUP_MEMORY_TEMPORARY, 343 #endif 344 data->data, data->size); 335 345 env->data = data; 336 346 smlTransportDataRef(data); 337 smlTrace(TRACE_INTERNAL, "%s: data: %s", __func__, g_str dup(msg->request.body));347 smlTrace(TRACE_INTERNAL, "%s: data: %s", __func__, g_strndup(data->data, data->size)); 338 348 339 349 soup_session_queue_message(env->session, msg, _msgReceived, userdata); 340 350 -
libsyncml/transports/http_server_internals.h
old new 21 21 #ifndef _HTTP_SERVER_INTERNALS_H_ 22 22 #define _HTTP_SERVER_INTERNALS_H_ 23 23 24 #include <libsoup/soup-session.h>25 24 #include <libsoup/soup-uri.h> 26 25 #include <libsoup/soup-server.h> 26 #ifdef HAVE_LIBSOUP22 27 27 #include <libsoup/soup-server-message.h> 28 #else 29 #include <libsoup/soup-message.h> 30 #endif 28 31 29 32 typedef struct SmlTransportHttpServerEnv { 30 33 SoupServer *server; -
libsyncml/transports/http_server.c
old new 36 36 */ 37 37 /*@{*/ 38 38 39 #ifdef HAVE_LIBSOUP22 39 40 static void _server_callback(SoupServerContext *context, SoupMessage *msg, gpointer data) 40 41 { 41 42 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, context, msg, data); … … 132 133 smlErrorDeref(&error); 133 134 } 134 135 136 #else /* !HAVE_LIBSOUP22 */ 137 138 static void _server_callback(SoupServer *server, 139 SoupMessage *msg, 140 const char *path, 141 GHashTable *query, 142 SoupClientContext *client, 143 gpointer data) 144 { 145 smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p, %p, %p)", __func__, server, msg, path, query, client, data); 146 SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN; 147 smlAssert(data); 148 SmlTransportHttpServerEnv *env = data; 149 SmlError *error = NULL; 150 151 smlTrace(TRACE_INTERNAL, "%s %s HTTP/1.%d", msg->method, path, soup_message_get_http_version(msg)); 152 153 if (msg->method != SOUP_METHOD_POST) { 154 smlErrorSet(&error, SML_ERROR_NOT_SUPPORTED, "Wrong method"); 155 soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); 156 goto error; 157 } 158 159 if (env->url && g_strcasecmp(path, env->url)) { 160 smlErrorSet(&error, SML_ERROR_FILE_NOT_FOUND, "Not Found"); 161 soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); 162 goto error; 163 } 164 165 const char *header = soup_message_headers_get(msg->request_headers, "Content-Type"); 166 if (header && !g_strncasecmp(header, SML_ELEMENT_XML, strlen(SML_ELEMENT_XML))) 167 mimetype = SML_MIMETYPE_XML; 168 else if(header && !g_strncasecmp(header, SML_ELEMENT_WBXML, strlen(SML_ELEMENT_WBXML))) 169 mimetype = SML_MIMETYPE_WBXML; 170 else if(header && !g_strncasecmp(header, SML_ELEMENT_SAN, strlen(SML_ELEMENT_SAN))) 171 mimetype = SML_MIMETYPE_SAN; 172 else if (header) { 173 smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mimetype"); 174 soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); 175 goto error; 176 } else { 177 smlErrorSet(&error, SML_ERROR_GENERIC, "Faulty mimetype"); 178 soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); 179 goto error; 180 } 181 182 if (!msg->request_body->length) { 183 /* Tolerate empty message for now. Http client transport could send empty messages 184 for initialization. Throwing an error here breaks testcase: manager_start_session 185 Empty Message for initialization got introduced with r251. 186 It's not fixed yet if r251 will be the final implementation for http client initalization. */ 187 188 /* FIXME: why does it do this? This causes a leak in both 189 * the client and the server, because the server never finishes 190 * responding to the request. 191 */ 192 soup_server_pause_message(server, msg); 193 smlTrace(TRACE_EXIT, "%s (empty message! tolerated for now ...)", __func__); 194 return; 195 196 /* FIXME: Throw an error again if changes in r251 got clarified/fixed. */ 197 /* 198 smlErrorSet(&error, SML_ERROR_GENERIC, "No data sent"); 199 soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); 200 goto error; 201 */ 202 } 203 204 SmlLink *link = smlLinkNew(env->tsp, msg, &error); 205 if (!link) 206 goto error; 207 208 SmlTransportData *tspdata = smlTransportDataNew((char *)msg->request_body->data, msg->request_body->length, mimetype, FALSE, &error); 209 if (!tspdata) 210 goto error_unref_msg; 211 212 smlTransportReceiveEvent(env->tsp, link, SML_TRANSPORT_EVENT_DATA, tspdata, NULL); 213 214 smlLinkDeref(link); 215 smlTransportDataDeref(tspdata); 216 217 soup_server_pause_message(server, msg); 218 219 smlTrace(TRACE_EXIT, "%s", __func__); 220 return; 221 222 error_unref_msg: 223 smlLinkDeref(link); 224 error: 225 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error)); 226 smlErrorDeref(&error); 227 } 228 229 #endif /* HAVE_LIBSOUP22 */ 230 135 231 /*@}*/ 136 232 137 233 /** … … 181 277 goto error_free_env; 182 278 } 183 279 280 #ifdef HAVE_LIBSOUP22 184 281 soup_server_add_handler(env->server, NULL, NULL, _server_callback, NULL, env); 282 #else 283 soup_server_add_handler(env->server, NULL, _server_callback, env, NULL); 284 #endif 185 285 186 286 soup_server_run_async(env->server); 187 287 … … 206 306 smlAssert(env->tsp); 207 307 208 308 soup_server_quit(env->server); 209 //g_object_unref(env->server);309 g_object_unref(env->server); 210 310 211 311 g_free(env->url); 212 312 g_free(env->interface); … … 230 330 if (error) 231 331 goto error_free_message; 232 332 233 // duplicate the data because sometimes data is freed to early234 char *soupcopy = (char *) smlTryMalloc0(data->size, &error);235 if (error)236 goto error_free_message;237 memcpy(soupcopy, data->data, data->size);238 239 333 soup_message_set_status (msg, SOUP_STATUS_OK); 334 #ifdef HAVE_LIBSOUP22 240 335 soup_server_message_set_encoding (SOUP_SERVER_MESSAGE(msg), SOUP_TRANSFER_CONTENT_LENGTH); 336 #endif 241 337 338 const char *content_type; 242 339 switch (data->type) { 243 340 case SML_MIMETYPE_XML: 244 soup_message_add_header(msg->response_headers, "Accept", "application/vnd.syncml+xml"); 245 soup_message_set_response (msg, "application/vnd.syncml+xml", SOUP_BUFFER_SYSTEM_OWNED, 246 soupcopy, data->size); 341 content_type = "application/vnd.syncml+xml"; 247 342 break; 248 343 case SML_MIMETYPE_WBXML: 249 soup_message_add_header(msg->response_headers, "Accept", "application/vnd.syncml+wbxml"); 250 soup_message_set_response (msg, "application/vnd.syncml+wbxml", SOUP_BUFFER_SYSTEM_OWNED, 251 soupcopy, data->size); 344 content_type = "application/vnd.syncml+wbxml"; 252 345 break; 253 346 default: 254 347 smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown Mimetype"); 255 348 goto error_free_message; 256 349 } 257 350 351 /* FIXME: Why do we add Accept to the response headers? Accept 352 * is only defined as a request header. Is this just a bug? 353 */ 354 355 #ifdef HAVE_LIBSOUP22 356 soup_message_add_header(msg->response_headers, "Accept", content_type); 357 // duplicate the data because sometimes data is freed to early 358 char *soupcopy = (char *) smlTryMalloc0(data->size, &error); 359 if (error) 360 goto error_free_message; 361 memcpy(soupcopy, data->data, data->size); 362 soup_message_set_response (msg, "application/vnd.syncml+xml", SOUP_BUFFER_SYSTEM_OWNED, 363 soupcopy, data->size); 258 364 soup_message_io_unpause(msg); 365 #else 366 soup_message_headers_append(msg->response_headers, "Accept", content_type); 367 soup_message_set_response(msg, "application/vnd.syncml+xml", 368 SOUP_MEMORY_COPY, data->data, data->size); 369 soup_server_unpause_message(env->server, msg); 370 #endif 259 371 260 // FIXME: the documentation of libsoup never show an example with such a call261 // FIXME: msg is perhaps in use by libsoup because this is asynchronous I/O262 // g_object_unref(msg);263 264 372 smlTrace(TRACE_EXIT, "%s", __func__); 265 373 return; 266 374 … … 270 378 else 271 379 soup_message_set_status_full(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR, smlErrorPrint(&error)); 272 380 381 #ifdef HAVE_LIBSOUP22 273 382 soup_server_message_set_encoding (SOUP_SERVER_MESSAGE (msg), SOUP_TRANSFER_CONTENT_LENGTH); 274 383 soup_message_io_unpause(msg); 384 #else 385 soup_server_unpause_message(env->server, msg); 386 #endif 275 387 276 388 // g_object_unref(msg); 277 389 smlErrorDeref(&error); -
CMakeLists.txt
old new 47 47 48 48 # find requirements 49 49 SET ( OPENOBEX_MIN_VERSION "1.1" ) 50 SET ( LIBSOUP2_MIN_VERSION "2.2.91" ) 50 SET ( LIBSOUP22_MIN_VERSION "2.2.91" ) 51 SET ( LIBSOUP24_MIN_VERSION "2.3.0.1" ) 51 52 #SET ( LIBWBXML2_MIN_VERSION "0.9.0" ) 52 53 #SET ( BLUEZ_MIN_VERSION "3.19" ) 53 54 -
config.h.cmake
old new 6 6 /* Http Transport */ 7 7 #cmakedefine ENABLE_HTTP 8 8 9 /* libsoup version in use */ 10 #cmakedefine HAVE_LIBSOUP22 11 #cmakedefine HAVE_LIBSOUP24 12 9 13 /* Obex Transport */ 10 14 #cmakedefine ENABLE_OBEX 11 15 -
cmake/modules/FindLibSoup2.cmake
old new 2 2 # Find libsoup headers, libraries and the answer to all questions. 3 3 # 4 4 # LIBSOUP2_FOUND True if libsoup got found 5 # LIBSOUP2_INCLUDE_DIRS Location of libsoup headers5 # LIBSOUP2_INCLUDE_DIRS Location of libsoup headers 6 6 # LIBSOUP2_LIBRARIES List of libaries to use libsoup 7 7 # 8 8 # Copyright (c) 2007 Daniel Gollub <dgollub@suse.de> … … 21 21 SET( _pkgconfig_REQUIRED "" ) 22 22 ENDIF ( LibSoup2_FIND_REQUIRED ) 23 23 24 IF ( LIBSOUP2 _MIN_VERSION )25 PKG_SEARCH_MODULE( LIBSOUP2 ${_pkgconfig_REQUIRED} libsoup-2. 2>=${LIBSOUP2_MIN_VERSION} libsoup2>=${LIBSOUP2_MIN_VERSION} )26 ELSE ( LIBSOUP2 _MIN_VERSION )27 PKG_SEARCH_MODULE( LIBSOUP2 ${_pkgconfig_REQUIRED} libsoup-2. 2libsoup2 )28 ENDIF ( LIBSOUP2 _MIN_VERSION )24 IF ( LIBSOUP24_MIN_VERSION ) 25 PKG_SEARCH_MODULE( LIBSOUP2 ${_pkgconfig_REQUIRED} libsoup-2.4>=${LIBSOUP24_MIN_VERSION} libsoup2>=${LIBSOUP24_MIN_VERSION} ) 26 ELSE ( LIBSOUP24_MIN_VERSION ) 27 PKG_SEARCH_MODULE( LIBSOUP2 ${_pkgconfig_REQUIRED} libsoup-2.4 libsoup2 ) 28 ENDIF ( LIBSOUP24_MIN_VERSION ) 29 29 30 IF ( LIBSOUP2_FOUND ) 31 OPTION ( HAVE_LIBSOUP24 "building with libsoup 2.4" ON ) 32 OPTION ( HAVE_LIBSOUP22 "building with libsoup 2.2" OFF ) 33 ELSE ( LIBSOUP2_FOUND ) 34 IF ( LIBSOUP22_MIN_VERSION ) 35 PKG_SEARCH_MODULE( LIBSOUP2 ${_pkgconfig_REQUIRED} libsoup-2.2>=${LIBSOUP22_MIN_VERSION} libsoup2>=${LIBSOUP22_MIN_VERSION} ) 36 ELSE ( LIBSOUP22_MIN_VERSION ) 37 PKG_SEARCH_MODULE( LIBSOUP2 ${_pkgconfig_REQUIRED} libsoup-2.2 libsoup2 ) 38 ENDIF ( LIBSOUP22_MIN_VERSION ) 30 39 40 IF ( LIBSOUP2_FOUND ) 41 SET ( HAVE_LIBSOUP24 OFF ) 42 SET ( HAVE_LIBSOUP22 ON ) 43 ENDIF ( LIBSOUP2_FOUND ) 44 ENDIF ( LIBSOUP2_FOUND ) 45 31 46 IF( NOT LIBSOUP2_FOUND AND NOT PKG_CONFIG_FOUND ) 32 47 33 48 FIND_PATH( _libsoup2_include_DIR libsoup/soup.h PATH_SUFFIXES libsoup libsoup-2.2 )
