22 #include <libsyncml/syncml.h>
23 #include <libsyncml/syncml_internals.h>
24 #include <libsyncml/sml_error_internals.h>
26 #include <libsyncml/sml_transport_internals.h>
28 #include "http_client_internals.h"
31 static void smlTransportHttpClientDisconnect(
void *data,
void *linkdata);
32 static SmlBool smlTransportHttpClientFinalize(
void *data,
SmlError **error);
35 #define soup_message_headers_get soup_message_get_header
36 #define soup_message_headers_append soup_message_add_header
40 static void smlTransportHttpClientCallback(SoupMessage *msg, gpointer userdata)
42 smlTrace(TRACE_ENTRY,
"%s(%p, %p)", __func__, msg, userdata);
44 static void smlTransportHttpClientCallback(SoupSession *session, SoupMessage *msg, gpointer userdata)
47 smlTrace(TRACE_ENTRY,
"%s(%p, %p, %p)", __func__, session, msg, userdata);
53 if (env->connectDone && msg->status_code == SOUP_STATUS_CANCELLED)
58 smlTrace(TRACE_EXIT,
"%s - ignoring due to shutdown", __func__);
63 if (!env->connectDone)
69 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
73 "Connection failed (%d) - %s", msg->status_code, msg->reason_phrase);
82 smlTrace(TRACE_INTERNAL,
"%s: Connect done", __func__);
83 if (!env->tsp->connected)
88 smlTransportReceiveEvent(
90 SML_TRANSPORT_EVENT_CONNECT_DONE,
94 env->connectDone = TRUE;
96 smlTrace(TRACE_INTERNAL,
"%s: Result: %d %s",
97 __func__, msg->status_code, msg->reason_phrase);
102 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
103 smlErrorSet(&error, SML_ERROR_GENERIC,
"Call not successfull: %d %s",
104 msg->status_code, msg->reason_phrase);
109 const char *header = soup_message_headers_get(msg->response_headers,
"Content-Type");
110 smlTrace(TRACE_INTERNAL,
"%s: content type ::= %s",
113 SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN;
114 if (header && !g_strncasecmp(header, SML_ELEMENT_XML, strlen(SML_ELEMENT_XML)))
115 mimetype = SML_MIMETYPE_XML;
116 else if(header && !g_strncasecmp(header, SML_ELEMENT_WBXML, strlen(SML_ELEMENT_WBXML)))
117 mimetype = SML_MIMETYPE_WBXML;
118 else if(header && !g_strncasecmp(header, SML_ELEMENT_SAN, strlen(SML_ELEMENT_SAN)))
119 mimetype = SML_MIMETYPE_SAN;
121 smlErrorSet(&error, SML_ERROR_GENERIC,
"Unknown mimetype");
124 smlErrorSet(&error, SML_ERROR_GENERIC,
"Faulty mimetype");
133 #ifdef HAVE_LIBSOUP22
134 length = msg->response.length;
136 length = msg->response_body->length;
138 smlTrace(TRACE_INTERNAL,
"%s: The message length is %i.", __func__, length);
152 #ifdef HAVE_LIBSOUP22
153 memcpy(data, msg->response.body, length);
155 memcpy(data, msg->response_body->data, length);
158 SmlTransportData *tspdata = smlTransportDataNew(data, length, mimetype, TRUE, &error);
161 goto error_free_data;
164 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DATA, tspdata, NULL);
167 smlTransportDataDeref(tspdata);
169 smlTrace(TRACE_EXIT,
"%s", __func__);
175 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error);
177 smlErrorDeref(&error);
188 #ifdef HAVE_LIBSOUP22
190 _authenticate (SoupSession *session, SoupMessage *msg,
191 const char *auth_type,
const char *auth_realm,
192 char **username,
char **password, gpointer data)
195 smlTrace(TRACE_INTERNAL,
"%s: authentication via auth_type %s", __func__, VA_STRING(auth_type));
196 *username = g_strdup(env->username);
197 *password = g_strdup(env->password);
201 _authenticate (SoupSession *session, SoupMessage *msg,
202 SoupAuth *auth, gboolean retrying, gpointer data)
204 smlTrace(TRACE_INTERNAL,
"%s(%p, %p, %p, %d, %p)", __func__, session, msg, auth, retrying, data);
206 smlTrace(TRACE_INTERNAL,
"%s: authentication via auth_type %s", __func__, VA_STRING(soup_auth_get_scheme_name(auth)));
209 soup_auth_authenticate(auth, env->username, env->password);
213 static SmlBool smlTransportHttpClientSetConfigOption(
219 smlTrace(TRACE_ENTRY,
"%s(%p, %s, %s, %p)", __func__, tsp, VA_STRING(name), VA_STRING(value), error);
222 smlAssert(tsp->transport_data);
225 if (!strcmp(name, SML_TRANSPORT_CONFIG_URL)) {
227 smlSafeCFree(&(env->url));
229 soup_uri_free(env->uri);
230 env->url = g_strdup(value);
231 env->uri = soup_uri_new(env->url);
232 if (env->uri == NULL) {
233 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
234 "The configured url %s is wrong.", env->url);
238 smlTrace(TRACE_INTERNAL,
"%s: URL %s detected", __func__, VA_STRING(env->url));
239 }
else if (!strcmp(name, SML_TRANSPORT_CONFIG_PROXY)) {
240 env->proxy = g_strdup(value);
241 smlTrace(TRACE_INTERNAL,
"%s: PROXY %s detected", __func__, VA_STRING(env->proxy));
242 }
else if (!strcmp(name, SML_TRANSPORT_CONFIG_USERNAME)) {
243 env->username = g_strdup(value);
244 smlTrace(TRACE_INTERNAL,
"%s: USERNAME %s detected", __func__, VA_STRING(env->username));
245 }
else if (!strcmp(name, SML_TRANSPORT_CONFIG_PASSWORD)) {
246 env->password = g_strdup(value);
247 smlTrace(TRACE_INTERNAL,
"%s: PASSWORD ******* detected", __func__);
248 }
else if (!strcmp(name, SML_TRANSPORT_CONFIG_SSL_CA_FILE)) {
249 env->cafile = g_strdup(value);
250 smlTrace(TRACE_INTERNAL,
"%s: SSL_CA_FILE %s detected", __func__, VA_STRING(env->cafile));
252 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
"Unknown parameter %s found.", name);
257 smlTrace(TRACE_EXIT,
"%s", __func__);
264 static void smlTransportHttpClientConnect(
void *data)
266 smlTrace(TRACE_ENTRY,
"%s(%p)", __func__, data);
271 if (!env->tsp->context)
273 smlErrorSet(&error, SML_ERROR_INTERNAL_MISCONFIGURATION,
274 "HTTP client runs only in asynchronous mode. So the context must be set.");
278 env->connectDone = FALSE;
279 env->disconnectDone = FALSE;
281 if (env->proxy != NULL && strlen(env->proxy) > 0)
283 if (env->cafile != NULL && strlen(env->cafile))
285 #ifdef HAVE_LIBSOUP22_SOLARIS
286 env->session = soup_session_sync_new_with_options(
288 env->session = soup_session_async_new_with_options(
289 SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context,
291 SOUP_SESSION_PROXY_URI, env->proxy,
292 SOUP_SESSION_SSL_CA_FILE, env->cafile,
299 #ifdef HAVE_LIBSOUP22_SOLARIS
300 env->session = soup_session_sync_new_with_options(
302 env->session = soup_session_async_new_with_options(
303 SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context,
305 SOUP_SESSION_PROXY_URI, env->proxy,
309 if (env->cafile != NULL && strlen(env->cafile))
311 #ifdef HAVE_LIBSOUP22_SOLARIS
312 env->session = soup_session_sync_new_with_options(
314 env->session = soup_session_async_new_with_options(
315 SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context,
317 SOUP_SESSION_SSL_CA_FILE, env->cafile,
320 #ifdef HAVE_LIBSOUP22_SOLARIS
321 env->session = soup_session_sync_new();
323 env->session = soup_session_async_new_with_options(
324 SOUP_SESSION_ASYNC_CONTEXT, env->tsp->context,
330 smlErrorSet(&error, SML_ERROR_GENERIC,
"Unable to create new session");
337 if (env->username || env->password)
339 g_signal_connect (env->session,
"authenticate", G_CALLBACK (_authenticate), env);
341 env->username = NULL;
342 env->password = NULL;
345 smlTrace(TRACE_EXIT,
"%s: %p", __func__, env);
349 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error);
352 static SmlBool smlTransportHttpClientSetResponseURI(
357 smlTrace(TRACE_ENTRY,
"%s(%p, %s, %p)", __func__, tsp, VA_STRING(uri), error);
360 smlAssert(tsp->transport_data);
365 smlSafeCFree(&(env->url));
367 soup_uri_free(env->uri);
369 env->url = g_strdup(uri);
370 env->uri = soup_uri_new(env->url);
371 if (env->uri == NULL) {
372 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
373 "The specified url \"%s\" is wrong.", env->url);
378 smlTrace(TRACE_EXIT,
"%s", __func__);
382 static SmlBool smlTransportHttpClientCleanupSession(
386 smlTrace(TRACE_ENTRY,
"%s", __func__);
390 SoupSession *session = data;
392 soup_session_abort(session);
393 g_object_unref(session);
395 smlTrace(TRACE_EXIT,
"%s", __func__);
399 static SmlBool smlTransportHttpClientFinalize(
void *data,
SmlError **error)
401 smlTrace(TRACE_ENTRY,
"%s(%p, %p)", __func__, data, error);
410 if (!
smlThreadCallFunction(env->tsp->thread, smlTransportHttpClientCleanupSession, env->session, error))
416 soup_uri_free(env->uri);
419 smlSafeCFree(&(env->url));
422 smlSafeCFree(&(env->proxy));
424 smlSafeFree((gpointer *)&env);
426 smlTrace(TRACE_EXIT,
"%s", __func__);
435 smlTrace(TRACE_ENTRY,
"%s(%p, %p, %p, %p)", __func__, userdata, link_, data, error);
436 smlAssert(error || data);
445 if (!env->connectDone)
446 smlTransportHttpClientConnect(userdata);
448 SoupMessage *msg = soup_message_new_from_uri(SOUP_METHOD_POST, env->uri);
450 smlErrorSet(&error, SML_ERROR_GENERIC,
"unknown libsoup error during message_new");
454 const char *content_type;
455 switch (data->type) {
456 case SML_MIMETYPE_XML:
457 content_type = SML_ELEMENT_XML;
459 case SML_MIMETYPE_WBXML:
460 content_type = SML_ELEMENT_WBXML;
462 case SML_MIMETYPE_SAN:
463 content_type = SML_ELEMENT_SAN;
466 smlErrorSet(&error, SML_ERROR_GENERIC,
"Unknown Mimetype %d", data->type);
467 goto error_free_message;
470 soup_message_headers_append(msg->request_headers,
"Accept", content_type);
471 soup_message_set_request (msg, content_type,
472 #ifdef HAVE_LIBSOUP22
473 SOUP_BUFFER_SYSTEM_OWNED,
477 g_memdup(data->data, data->size), data->size);
479 #ifdef HAVE_LIBSOUP22
480 smlTrace(TRACE_INTERNAL,
"%s: data length: %i", __func__, msg->request.length);
483 smlTrace(TRACE_INTERNAL,
"%s: data length: %i", __func__, msg->request_body->length);
486 #ifdef HAVE_LIBSOUP22_SOLARIS
487 soup_session_send_message(env->session, msg);
488 smlTrace(TRACE_INTERNAL,
"%s: sent message and starting callback", __func__);
489 smlTransportHttpClientCallback(msg, userdata);
492 soup_session_queue_message(env->session, msg, smlTransportHttpClientCallback, userdata);
495 smlTrace(TRACE_EXIT,
"%s", __func__);
501 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error);
503 smlErrorDeref(&error);
506 static void smlTransportHttpClientDisconnect(
void *data,
void *linkdata)
508 smlTrace(TRACE_ENTRY,
"%s(%p, %p)", __func__, data, linkdata);
514 if (!env->connectDone && !env->session)
517 env->disconnectDone = TRUE;
518 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL);
519 smlTrace(TRACE_EXIT,
"%s - ignoring because never connected", __func__);
523 smlAssert(env->session);
532 soup_session_abort(env->session);
533 g_object_unref(env->session);
537 env->disconnectDone = FALSE;
538 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL);
540 smlTrace(TRACE_EXIT,
"%s", __func__);
548 #ifdef HAVE_LIBSOUP22_SOLARIS
549 smlTrace(TRACE_INTERNAL,
"%s: Enabled libsoup 2.2 Solaris workarounds", __func__);
552 tsp->functions.set_config_option = smlTransportHttpClientSetConfigOption;
553 tsp->functions.set_response_uri = smlTransportHttpClientSetResponseURI;
554 tsp->functions.disconnect = smlTransportHttpClientDisconnect;
555 tsp->functions.finalize = smlTransportHttpClientFinalize;
556 tsp->functions.send = smlTransportHttpClientSend;
561 tsp->transport_data = env;