1 /*
2 * librest - RESTful web services access
3 * Copyright (c) 2008, 2009, Intel Corporation.
4 *
5 * Authors: Rob Bradford <rob@linux.intel.com>
6 * Ross Burton <ross@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU Lesser General Public License,
10 * version 2.1, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23 #include <config.h>
24 #include <string.h>
25
26 #include <libsoup/soup.h>
27 #if WITH_GNOME
28 #include <libsoup/soup-gnome.h>
29 #endif
30
31 #include "rest-marshal.h"
32 #include "rest-proxy-auth-private.h"
33 #include "rest-proxy.h"
34 #include "rest-private.h"
35
36 G_DEFINE_TYPE (RestProxy, rest_proxy, G_TYPE_OBJECT)
37
38 #define GET_PRIVATE(o) \
39 (G_TYPE_INSTANCE_GET_PRIVATE ((o), REST_TYPE_PROXY, RestProxyPrivate))
40
41 typedef struct _RestProxyPrivate RestProxyPrivate;
42
43 struct _RestProxyPrivate {
44 gchar *url_format;
45 gchar *url;
46 gchar *user_agent;
47 gchar *username;
48 gchar *password;
49 gboolean binding_required;
50 SoupSession *session;
51 SoupSession *session_sync;
52 gboolean disable_cookies;
53 char *ssl_ca_file;
54 };
55
56 enum
57 {
58 PROP0 = 0,
59 PROP_URL_FORMAT,
60 PROP_BINDING_REQUIRED,
61 PROP_USER_AGENT,
62 PROP_DISABLE_COOKIES,
63 PROP_USERNAME,
64 PROP_PASSWORD,
65 PROP_SSL_STRICT,
66 PROP_SSL_CA_FILE
67 };
68
69 enum {
70 AUTHENTICATE,
71 LAST_SIGNAL
72 };
73
74 static guint signals[LAST_SIGNAL] = { 0 };
75
76
77 static gboolean _rest_proxy_simple_run_valist (RestProxy *proxy,
78 char **payload,
79 goffset *len,
80 GError **error,
81 va_list params);
82
83 static RestProxyCall *_rest_proxy_new_call (RestProxy *proxy);
84
85 static gboolean _rest_proxy_bind_valist (RestProxy *proxy,
86 va_list params);
87
88 GQuark
rest_proxy_error_quark(void)89 rest_proxy_error_quark (void)
90 {
91 return g_quark_from_static_string ("rest-proxy-error-quark");
92 }
93
94 static void
rest_proxy_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)95 rest_proxy_get_property (GObject *object,
96 guint property_id,
97 GValue *value,
98 GParamSpec *pspec)
99 {
100 RestProxyPrivate *priv = GET_PRIVATE (object);
101
102 switch (property_id) {
103 case PROP_URL_FORMAT:
104 g_value_set_string (value, priv->url_format);
105 break;
106 case PROP_BINDING_REQUIRED:
107 g_value_set_boolean (value, priv->binding_required);
108 break;
109 case PROP_USER_AGENT:
110 g_value_set_string (value, priv->user_agent);
111 break;
112 case PROP_DISABLE_COOKIES:
113 g_value_set_boolean (value, priv->disable_cookies);
114 break;
115 case PROP_USERNAME:
116 g_value_set_string (value, priv->username);
117 break;
118 case PROP_PASSWORD:
119 g_value_set_string (value, priv->password);
120 break;
121 case PROP_SSL_STRICT: {
122 gboolean ssl_strict;
123 g_object_get (G_OBJECT(priv->session),
124 "ssl-strict", &ssl_strict,
125 NULL);
126 g_value_set_boolean (value, ssl_strict);
127 break;
128 }
129 case PROP_SSL_CA_FILE:
130 g_value_set_string (value, priv->ssl_ca_file);
131 break;
132
133 default:
134 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
135 }
136 }
137
138 static void
rest_proxy_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)139 rest_proxy_set_property (GObject *object,
140 guint property_id,
141 const GValue *value,
142 GParamSpec *pspec)
143 {
144 RestProxyPrivate *priv = GET_PRIVATE (object);
145
146 switch (property_id) {
147 case PROP_URL_FORMAT:
148 g_free (priv->url_format);
149 priv->url_format = g_value_dup_string (value);
150
151 /* Clear the cached url */
152 g_free (priv->url);
153 priv->url = NULL;
154 break;
155 case PROP_BINDING_REQUIRED:
156 priv->binding_required = g_value_get_boolean (value);
157
158 /* Clear cached url */
159 g_free (priv->url);
160 priv->url = NULL;
161 break;
162 case PROP_USER_AGENT:
163 g_free (priv->user_agent);
164 priv->user_agent = g_value_dup_string (value);
165 break;
166 case PROP_DISABLE_COOKIES:
167 priv->disable_cookies = g_value_get_boolean (value);
168 break;
169 case PROP_USERNAME:
170 g_free (priv->username);
171 priv->username = g_value_dup_string (value);
172 break;
173 case PROP_PASSWORD:
174 g_free (priv->password);
175 priv->password = g_value_dup_string (value);
176 break;
177 case PROP_SSL_STRICT:
178 g_object_set (G_OBJECT(priv->session),
179 "ssl-strict", g_value_get_boolean (value),
180 NULL);
181 g_object_set (G_OBJECT(priv->session_sync),
182 "ssl-strict", g_value_get_boolean (value),
183 NULL);
184 break;
185 case PROP_SSL_CA_FILE:
186 g_free(priv->ssl_ca_file);
187 priv->ssl_ca_file = g_value_dup_string (value);
188 break;
189 default:
190 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
191 }
192 }
193
194 static void
rest_proxy_dispose(GObject * object)195 rest_proxy_dispose (GObject *object)
196 {
197 RestProxyPrivate *priv = GET_PRIVATE (object);
198
199 if (priv->session)
200 {
201 g_object_unref (priv->session);
202 priv->session = NULL;
203 }
204
205 if (priv->session_sync)
206 {
207 g_object_unref (priv->session_sync);
208 priv->session_sync = NULL;
209 }
210
211 G_OBJECT_CLASS (rest_proxy_parent_class)->dispose (object);
212 }
213
214 static gboolean
default_authenticate_cb(RestProxy * self,G_GNUC_UNUSED RestProxyAuth * auth,gboolean retrying)215 default_authenticate_cb (RestProxy *self,
216 G_GNUC_UNUSED RestProxyAuth *auth,
217 gboolean retrying)
218 {
219 /* We only want to try the credentials once, otherwise we get in an
220 * infinite loop with failed credentials, retrying the same invalid
221 * ones again and again
222 */
223 return !retrying;
224 }
225
226 static void
authenticate(RestProxy * self,SoupMessage * msg,SoupAuth * soup_auth,gboolean retrying,SoupSession * session)227 authenticate (RestProxy *self,
228 SoupMessage *msg,
229 SoupAuth *soup_auth,
230 gboolean retrying,
231 SoupSession *session)
232 {
233 RestProxyPrivate *priv = GET_PRIVATE (self);
234 RestProxyAuth *rest_auth;
235 gboolean try_auth;
236
237 rest_auth = rest_proxy_auth_new (self, session, msg, soup_auth);
238 g_signal_emit(self, signals[AUTHENTICATE], 0, rest_auth, retrying, &try_auth);
239 if (try_auth && !rest_proxy_auth_is_paused (rest_auth))
240 soup_auth_authenticate (soup_auth, priv->username, priv->password);
241 g_object_unref (G_OBJECT (rest_auth));
242 }
243
244 static void
rest_proxy_constructed(GObject * object)245 rest_proxy_constructed (GObject *object)
246 {
247 RestProxyPrivate *priv = GET_PRIVATE (object);
248
249 if (!priv->disable_cookies) {
250 SoupSessionFeature *cookie_jar =
251 (SoupSessionFeature *)soup_cookie_jar_new ();
252 soup_session_add_feature (priv->session, cookie_jar);
253 soup_session_add_feature (priv->session_sync, cookie_jar);
254 g_object_unref (cookie_jar);
255 }
256
257 if (REST_DEBUG_ENABLED(PROXY)) {
258 SoupSessionFeature *logger = (SoupSessionFeature*)soup_logger_new (SOUP_LOGGER_LOG_BODY, 0);
259 soup_session_add_feature (priv->session, logger);
260 g_object_unref (logger);
261
262 logger = (SoupSessionFeature*)soup_logger_new (SOUP_LOGGER_LOG_BODY, 0);
263 soup_session_add_feature (priv->session_sync, logger);
264 g_object_unref (logger);
265 }
266
267 /* session lifetime is same as self, no need to keep signalid */
268 g_signal_connect_swapped (priv->session, "authenticate",
269 G_CALLBACK(authenticate), object);
270 g_signal_connect_swapped (priv->session_sync, "authenticate",
271 G_CALLBACK(authenticate), object);
272 }
273
274 static void
rest_proxy_finalize(GObject * object)275 rest_proxy_finalize (GObject *object)
276 {
277 RestProxyPrivate *priv = GET_PRIVATE (object);
278
279 g_free (priv->url);
280 g_free (priv->url_format);
281 g_free (priv->user_agent);
282 g_free (priv->username);
283 g_free (priv->password);
284 g_free (priv->ssl_ca_file);
285
286 G_OBJECT_CLASS (rest_proxy_parent_class)->finalize (object);
287 }
288
289 static void
rest_proxy_class_init(RestProxyClass * klass)290 rest_proxy_class_init (RestProxyClass *klass)
291 {
292 GParamSpec *pspec;
293 GObjectClass *object_class = G_OBJECT_CLASS (klass);
294 RestProxyClass *proxy_class = REST_PROXY_CLASS (klass);
295
296 _rest_setup_debugging ();
297
298 g_type_class_add_private (klass, sizeof (RestProxyPrivate));
299
300 object_class->get_property = rest_proxy_get_property;
301 object_class->set_property = rest_proxy_set_property;
302 object_class->dispose = rest_proxy_dispose;
303 object_class->constructed = rest_proxy_constructed;
304 object_class->finalize = rest_proxy_finalize;
305
306 proxy_class->simple_run_valist = _rest_proxy_simple_run_valist;
307 proxy_class->new_call = _rest_proxy_new_call;
308 proxy_class->bind_valist = _rest_proxy_bind_valist;
309
310 pspec = g_param_spec_string ("url-format",
311 "url-format",
312 "Format string for the RESTful url",
313 NULL,
314 G_PARAM_READWRITE);
315 g_object_class_install_property (object_class,
316 PROP_URL_FORMAT,
317 pspec);
318
319 pspec = g_param_spec_boolean ("binding-required",
320 "binding-required",
321 "Whether the URL format requires binding",
322 FALSE,
323 G_PARAM_READWRITE);
324 g_object_class_install_property (object_class,
325 PROP_BINDING_REQUIRED,
326 pspec);
327
328 pspec = g_param_spec_string ("user-agent",
329 "user-agent",
330 "The User-Agent of the client",
331 NULL,
332 G_PARAM_READWRITE);
333 g_object_class_install_property (object_class,
334 PROP_USER_AGENT,
335 pspec);
336
337 pspec = g_param_spec_boolean ("disable-cookies",
338 "disable-cookies",
339 "Whether to disable cookie support",
340 FALSE,
341 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
342 g_object_class_install_property (object_class,
343 PROP_DISABLE_COOKIES,
344 pspec);
345
346 pspec = g_param_spec_string ("username",
347 "username",
348 "The username for authentication",
349 NULL,
350 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
351 g_object_class_install_property (object_class,
352 PROP_USERNAME,
353 pspec);
354
355 pspec = g_param_spec_string ("password",
356 "password",
357 "The password for authentication",
358 NULL,
359 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
360 g_object_class_install_property (object_class,
361 PROP_PASSWORD,
362 pspec);
363
364 pspec = g_param_spec_boolean ("ssl-strict",
365 "Strictly validate SSL certificates",
366 "Whether certificate errors should be considered a connection error",
367 TRUE,
368 G_PARAM_READWRITE);
369 g_object_class_install_property (object_class,
370 PROP_SSL_STRICT,
371 pspec);
372
373 pspec = g_param_spec_string ("ssl-ca-file",
374 "SSL CA file",
375 "File containing SSL CA certificates.",
376 NULL,
377 G_PARAM_READWRITE);
378 g_object_class_install_property (object_class,
379 PROP_SSL_CA_FILE,
380 pspec);
381
382 /**
383 * RestProxy::authenticate:
384 * @proxy: the proxy
385 * @auth: authentication state
386 * @retrying: %TRUE if this is the second (or later) attempt
387 *
388 * Emitted when the proxy requires authentication. If
389 * credentials are available, set the 'username' and 'password'
390 * properties on @proxy and return %TRUE from the callback.
391 * This will cause the signal emission to stop, and librest will
392 * try to connect with these credentials
393 * If these credentials fail, the signal will be
394 * emitted again, with @retrying set to %TRUE, which will
395 * continue until %FALSE is returned from the callback.
396 *
397 * If you call rest_proxy_auth_pause() on @auth before
398 * returning, then you can the authentication credentials on
399 * the #RestProxy object asynchronously. You have to make sure
400 * that @auth does not get destroyed with g_object_ref().
401 * You can then unpause the authentication with
402 * rest_proxy_auth_unpause() when everything is ready for it
403 * to continue.
404 **/
405 signals[AUTHENTICATE] =
406 g_signal_new ("authenticate",
407 G_OBJECT_CLASS_TYPE (object_class),
408 G_SIGNAL_RUN_LAST,
409 G_STRUCT_OFFSET (RestProxyClass, authenticate),
410 g_signal_accumulator_true_handled, NULL,
411 g_cclosure_user_marshal_BOOLEAN__OBJECT_BOOLEAN,
412 G_TYPE_BOOLEAN, 2,
413 REST_TYPE_PROXY_AUTH,
414 G_TYPE_BOOLEAN);
415
416 proxy_class->authenticate = default_authenticate_cb;
417 }
418
419 static void
rest_proxy_init(RestProxy * self)420 rest_proxy_init (RestProxy *self)
421 {
422 RestProxyPrivate *priv = GET_PRIVATE (self);
423
424 priv->session = soup_session_async_new ();
425 priv->session_sync = soup_session_sync_new ();
426
427 #ifdef REST_SYSTEM_CA_FILE
428 /* with ssl-strict (defaults TRUE) setting ssl-ca-file forces all
429 * certificates to be trusted */
430 g_object_set (priv->session,
431 "ssl-ca-file", REST_SYSTEM_CA_FILE,
432 NULL);
433 g_object_set (priv->session_sync,
434 "ssl-ca-file", REST_SYSTEM_CA_FILE,
435 NULL);
436 #endif
437 g_object_bind_property (self, "ssl-ca-file",
438 priv->session, "ssl-ca-file",
439 G_BINDING_BIDIRECTIONAL);
440 g_object_bind_property (self, "ssl-ca-file",
441 priv->session_sync, "ssl-ca-file",
442 G_BINDING_BIDIRECTIONAL);
443
444 #if WITH_GNOME
445 soup_session_add_feature_by_type (priv->session,
446 SOUP_TYPE_PROXY_RESOLVER_GNOME);
447 soup_session_add_feature_by_type (priv->session_sync,
448 SOUP_TYPE_PROXY_RESOLVER_GNOME);
449 #endif
450 }
451
452 /**
453 * rest_proxy_new:
454 * @url_format: the endpoint URL
455 * @binding_required: whether the URL needs to be bound before calling
456 *
457 * Create a new #RestProxy for the specified endpoint @url_format, using the
458 * "GET" method.
459 *
460 * Set @binding_required to %TRUE if the URL contains string formatting
461 * operations (for example "http://foo.com/%<!-- -->s". These must be expanded
462 * using rest_proxy_bind() before invoking the proxy.
463 *
464 * Returns: A new #RestProxy.
465 */
466 RestProxy *
rest_proxy_new(const gchar * url_format,gboolean binding_required)467 rest_proxy_new (const gchar *url_format,
468 gboolean binding_required)
469 {
470 return g_object_new (REST_TYPE_PROXY,
471 "url-format", url_format,
472 "binding-required", binding_required,
473 NULL);
474 }
475
476 /**
477 * rest_proxy_new_with_authentication:
478 * @url_format: the endpoint URL
479 * @binding_required: whether the URL needs to be bound before calling
480 * @username: the username provided by the user or client
481 * @password: the password provided by the user or client
482 *
483 * Create a new #RestProxy for the specified endpoint @url_format, using the
484 * "GET" method.
485 *
486 * Set @binding_required to %TRUE if the URL contains string formatting
487 * operations (for example "http://foo.com/%<!-- -->s". These must be expanded
488 * using rest_proxy_bind() before invoking the proxy.
489 *
490 * Returns: A new #RestProxy.
491 */
492 RestProxy *
rest_proxy_new_with_authentication(const gchar * url_format,gboolean binding_required,const gchar * username,const gchar * password)493 rest_proxy_new_with_authentication (const gchar *url_format,
494 gboolean binding_required,
495 const gchar *username,
496 const gchar *password)
497 {
498 return g_object_new (REST_TYPE_PROXY,
499 "url-format", url_format,
500 "binding-required", binding_required,
501 "username", username,
502 "password", password,
503 NULL);
504 }
505
506 static gboolean
_rest_proxy_bind_valist(RestProxy * proxy,va_list params)507 _rest_proxy_bind_valist (RestProxy *proxy,
508 va_list params)
509 {
510 RestProxyPrivate *priv = GET_PRIVATE (proxy);
511
512 g_return_val_if_fail (proxy != NULL, FALSE);
513 g_return_val_if_fail (priv->url_format != NULL, FALSE);
514 g_return_val_if_fail (priv->binding_required == TRUE, FALSE);
515
516 g_free (priv->url);
517
518 priv->url = g_strdup_vprintf (priv->url_format, params);
519
520 return TRUE;
521 }
522
523
524 gboolean
rest_proxy_bind_valist(RestProxy * proxy,va_list params)525 rest_proxy_bind_valist (RestProxy *proxy,
526 va_list params)
527 {
528 RestProxyClass *proxy_class = REST_PROXY_GET_CLASS (proxy);
529
530 return proxy_class->bind_valist (proxy, params);
531 }
532
533 gboolean
rest_proxy_bind(RestProxy * proxy,...)534 rest_proxy_bind (RestProxy *proxy, ...)
535 {
536 g_return_val_if_fail (REST_IS_PROXY (proxy), FALSE);
537
538 gboolean res;
539 va_list params;
540
541 va_start (params, proxy);
542 res = rest_proxy_bind_valist (proxy, params);
543 va_end (params);
544
545 return res;
546 }
547
548 void
rest_proxy_set_user_agent(RestProxy * proxy,const char * user_agent)549 rest_proxy_set_user_agent (RestProxy *proxy,
550 const char *user_agent)
551 {
552 g_return_if_fail (REST_IS_PROXY (proxy));
553
554 g_object_set (proxy, "user-agent", user_agent, NULL);
555 }
556
557 const gchar *
rest_proxy_get_user_agent(RestProxy * proxy)558 rest_proxy_get_user_agent (RestProxy *proxy)
559 {
560 RestProxyPrivate *priv;
561
562 g_return_val_if_fail (REST_IS_PROXY (proxy), NULL);
563
564 priv = GET_PRIVATE (proxy);
565
566 return priv->user_agent;
567 }
568
569 /**
570 * rest_proxy_add_soup_feature:
571 * @proxy: The #RestProxy
572 * @feature: A #SoupSessionFeature
573 *
574 * This method can be used to add specific features to the #SoupSession objects
575 * that are used by librest for its HTTP connections. For example, if one needs
576 * extensive control over the cookies which are used for the REST HTTP
577 * communication, it's possible to get full access to libsoup cookie API by
578 * using
579 *
580 * <programlisting>
581 * RestProxy *proxy = g_object_new(REST_TYPE_PROXY,
582 * "url-format", url,
583 * "disable-cookies", TRUE,
584 * NULL);
585 * SoupSessionFeature *cookie_jar = SOUP_SESSION_FEATURE(soup_cookie_jar_new ());
586 * rest_proxy_add_soup_feature(proxy, cookie_jar);
587 * </programlisting>
588 *
589 * Since: 0.7.92
590 */
591 void
rest_proxy_add_soup_feature(RestProxy * proxy,SoupSessionFeature * feature)592 rest_proxy_add_soup_feature (RestProxy *proxy, SoupSessionFeature *feature)
593 {
594 RestProxyPrivate *priv;
595
596 g_return_if_fail (REST_IS_PROXY(proxy));
597 priv = GET_PRIVATE (proxy);
598 g_return_if_fail (priv->session != NULL);
599 g_return_if_fail (priv->session_sync != NULL);
600
601 soup_session_add_feature (priv->session, feature);
602 soup_session_add_feature (priv->session_sync, feature);
603 }
604
605 static RestProxyCall *
_rest_proxy_new_call(RestProxy * proxy)606 _rest_proxy_new_call (RestProxy *proxy)
607 {
608 RestProxyCall *call;
609
610 call = g_object_new (REST_TYPE_PROXY_CALL,
611 "proxy", proxy,
612 NULL);
613
614 return call;
615 }
616
617 /**
618 * rest_proxy_new_call:
619 * @proxy: the #RestProxy
620 *
621 * Create a new #RestProxyCall for making a call to the web service. This call
622 * is one-shot and should not be re-used for making multiple calls.
623 *
624 * Returns: (transfer full): a new #RestProxyCall.
625 */
626 RestProxyCall *
rest_proxy_new_call(RestProxy * proxy)627 rest_proxy_new_call (RestProxy *proxy)
628 {
629 RestProxyClass *proxy_class = REST_PROXY_GET_CLASS (proxy);
630 return proxy_class->new_call (proxy);
631 }
632
633 gboolean
_rest_proxy_get_binding_required(RestProxy * proxy)634 _rest_proxy_get_binding_required (RestProxy *proxy)
635 {
636 RestProxyPrivate *priv;
637
638 g_return_val_if_fail (REST_IS_PROXY (proxy), FALSE);
639
640 priv = GET_PRIVATE (proxy);
641
642 return priv->binding_required;
643 }
644
645 const gchar *
_rest_proxy_get_bound_url(RestProxy * proxy)646 _rest_proxy_get_bound_url (RestProxy *proxy)
647 {
648 RestProxyPrivate *priv;
649
650 g_return_val_if_fail (REST_IS_PROXY (proxy), NULL);
651
652 priv = GET_PRIVATE (proxy);
653
654 if (!priv->url && !priv->binding_required)
655 {
656 priv->url = g_strdup (priv->url_format);
657 }
658
659 return priv->url;
660 }
661
662 static gboolean
_rest_proxy_simple_run_valist(RestProxy * proxy,gchar ** payload,goffset * len,GError ** error,va_list params)663 _rest_proxy_simple_run_valist (RestProxy *proxy,
664 gchar **payload,
665 goffset *len,
666 GError **error,
667 va_list params)
668 {
669 RestProxyCall *call;
670 gboolean ret;
671
672 g_return_val_if_fail (REST_IS_PROXY (proxy), FALSE);
673 g_return_val_if_fail (payload, FALSE);
674
675 call = rest_proxy_new_call (proxy);
676
677 rest_proxy_call_add_params_from_valist (call, params);
678
679 ret = rest_proxy_call_run (call, NULL, error);
680 if (ret) {
681 *payload = g_strdup (rest_proxy_call_get_payload (call));
682 if (len) *len = rest_proxy_call_get_payload_length (call);
683 } else {
684 *payload = NULL;
685 if (len) *len = 0;
686 }
687
688 g_object_unref (call);
689
690 return ret;
691 }
692
693 gboolean
rest_proxy_simple_run_valist(RestProxy * proxy,char ** payload,goffset * len,GError ** error,va_list params)694 rest_proxy_simple_run_valist (RestProxy *proxy,
695 char **payload,
696 goffset *len,
697 GError **error,
698 va_list params)
699 {
700 RestProxyClass *proxy_class = REST_PROXY_GET_CLASS (proxy);
701 return proxy_class->simple_run_valist (proxy, payload, len, error, params);
702 }
703
704 gboolean
rest_proxy_simple_run(RestProxy * proxy,gchar ** payload,goffset * len,GError ** error,...)705 rest_proxy_simple_run (RestProxy *proxy,
706 gchar **payload,
707 goffset *len,
708 GError **error,
709 ...)
710 {
711 va_list params;
712 gboolean ret;
713
714 g_return_val_if_fail (REST_IS_PROXY (proxy), FALSE);
715 g_return_val_if_fail (payload, FALSE);
716
717 va_start (params, error);
718 ret = rest_proxy_simple_run_valist (proxy,
719 payload,
720 len,
721 error,
722 params);
723 va_end (params);
724
725 return ret;
726 }
727
728 void
_rest_proxy_queue_message(RestProxy * proxy,SoupMessage * message,SoupSessionCallback callback,gpointer user_data)729 _rest_proxy_queue_message (RestProxy *proxy,
730 SoupMessage *message,
731 SoupSessionCallback callback,
732 gpointer user_data)
733 {
734 RestProxyPrivate *priv;
735
736 g_return_if_fail (REST_IS_PROXY (proxy));
737 g_return_if_fail (SOUP_IS_MESSAGE (message));
738
739 priv = GET_PRIVATE (proxy);
740
741 soup_session_queue_message (priv->session,
742 message,
743 callback,
744 user_data);
745 }
746
747 void
_rest_proxy_cancel_message(RestProxy * proxy,SoupMessage * message)748 _rest_proxy_cancel_message (RestProxy *proxy,
749 SoupMessage *message)
750 {
751 RestProxyPrivate *priv;
752
753 g_return_if_fail (REST_IS_PROXY (proxy));
754 g_return_if_fail (SOUP_IS_MESSAGE (message));
755
756 priv = GET_PRIVATE (proxy);
757 soup_session_cancel_message (priv->session,
758 message,
759 SOUP_STATUS_CANCELLED);
760 }
761
762 guint
_rest_proxy_send_message(RestProxy * proxy,SoupMessage * message)763 _rest_proxy_send_message (RestProxy *proxy,
764 SoupMessage *message)
765 {
766 RestProxyPrivate *priv;
767
768 g_return_val_if_fail (REST_IS_PROXY (proxy), 0);
769 g_return_val_if_fail (SOUP_IS_MESSAGE (message), 0);
770
771 priv = GET_PRIVATE (proxy);
772
773 return soup_session_send_message (priv->session_sync, message);
774 }
775