275
259
g_value_set_uint (value, wc->priv->throttling);
278
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
279
g_value_set_boolean (value, wc->priv->cache != NULL);
281
g_value_set_boolean (value, FALSE);
262
g_value_set_boolean(value, cache_is_available (wc));
284
264
case PROP_CACHE_SIZE:
285
g_value_set_uint (value, wc->priv->cache_size);
265
g_value_set_uint (value, cache_get_size (wc));
267
case PROP_USER_AGENT:
268
g_object_get_property (G_OBJECT (wc->priv->session), "user_agent", value);
288
271
G_OBJECT_WARN_INVALID_PROPERTY_ID (wc, propid, pspec);
293
parse_error (guint status,
295
const gchar *response,
296
GSimpleAsyncResult *result)
298
if (!response || *response == '\0')
302
case SOUP_STATUS_CANT_RESOLVE:
303
case SOUP_STATUS_CANT_CONNECT:
304
case SOUP_STATUS_SSL_FAILED:
305
case SOUP_STATUS_IO_ERROR:
306
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
307
GRL_NET_WC_ERROR_NETWORK_ERROR,
308
"Cannot connect to the server");
310
case SOUP_STATUS_CANT_RESOLVE_PROXY:
311
case SOUP_STATUS_CANT_CONNECT_PROXY:
312
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
313
GRL_NET_WC_ERROR_PROXY_ERROR,
314
"Cannot connect to the proxy server");
316
case SOUP_STATUS_INTERNAL_SERVER_ERROR: /* 500 */
317
case SOUP_STATUS_MALFORMED:
318
case SOUP_STATUS_BAD_REQUEST: /* 400 */
319
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
320
GRL_NET_WC_ERROR_PROTOCOL_ERROR,
321
"Invalid request URI or header: %s",
324
case SOUP_STATUS_UNAUTHORIZED: /* 401 */
325
case SOUP_STATUS_FORBIDDEN: /* 403 */
326
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
327
GRL_NET_WC_ERROR_AUTHENTICATION_REQUIRED,
328
"Authentication required: %s", response);
330
case SOUP_STATUS_NOT_FOUND: /* 404 */
331
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
332
GRL_NET_WC_ERROR_NOT_FOUND,
333
"The requested resource was not found: %s",
336
case SOUP_STATUS_CONFLICT: /* 409 */
337
case SOUP_STATUS_PRECONDITION_FAILED: /* 412 */
338
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
339
GRL_NET_WC_ERROR_CONFLICT,
340
"The entry has been modified since it was downloaded: %s",
343
case SOUP_STATUS_CANCELLED:
344
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
345
GRL_NET_WC_ERROR_CANCELLED,
346
"Operation was cancelled");
349
g_message ("Unhandled status: %s", soup_status_get_phrase (status));
353
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
355
read_async_cb (GObject *source, GAsyncResult *res, gpointer user_data)
357
GSimpleAsyncResult *result;
360
GError *error = NULL;
364
result = G_SIMPLE_ASYNC_RESULT (user_data);
365
rr = g_simple_async_result_get_op_res_gpointer (result);
367
s = g_input_stream_read_finish (G_INPUT_STREAM (source), res, &error);
369
/* Continue reading */
371
to_read = rr->length - rr->offset;
373
/* Buffer is not enough; we need to assign more space */
375
rr->buffer = g_renew (gchar, rr->buffer, rr->length);
376
to_read = rr->length - rr->offset;
378
g_input_stream_read_async (G_INPUT_STREAM (source), rr->buffer + rr->offset, to_read, G_PRIORITY_DEFAULT, NULL, read_async_cb, user_data);
382
/* Put the end of string */
383
rr->buffer[rr->offset] = '\0';
385
g_input_stream_close (G_INPUT_STREAM (source), NULL, NULL);
388
if (error->code == G_IO_ERROR_CANCELLED) {
389
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
390
GRL_NET_WC_ERROR_CANCELLED,
391
"Operation was cancelled");
393
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
394
GRL_NET_WC_ERROR_UNAVAILABLE,
395
"Data not available");
397
g_error_free (error);
399
g_simple_async_result_complete (result);
400
g_object_unref (result);
404
msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (rr->request));
407
if (msg->status_code != SOUP_STATUS_OK) {
408
parse_error (msg->status_code,
410
msg->response_body->data,
411
G_SIMPLE_ASYNC_RESULT (user_data));
412
g_object_unref (msg);
416
g_simple_async_result_complete (result);
417
g_object_unref (result);
421
reply_cb (GObject *source, GAsyncResult *res, gpointer user_data)
423
GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
424
RequestResult *rr = g_simple_async_result_get_op_res_gpointer (result);
425
GError *error = NULL;
427
GInputStream *in = soup_request_send_finish (rr->request, res, &error);
430
g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
431
GRL_NET_WC_ERROR_UNAVAILABLE,
432
"Data not available");
433
g_error_free (error);
435
g_simple_async_result_complete (result);
436
g_object_unref (result);
440
rr->length = soup_request_get_content_length (rr->request) + 1;
441
if (rr->length == 1) {
442
rr->length = BUFFER_SIZE;
444
rr->buffer = g_new (gchar, rr->length);
445
g_input_stream_read_async (in, rr->buffer, rr->length, G_PRIORITY_DEFAULT, NULL, read_async_cb, user_data);
451
reply_cb (SoupSession *session,
455
GSimpleAsyncResult *result;
456
gulong cancel_signal;
458
cancel_signal = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (msg),
461
GCancellable *cancellable;
463
cancellable = g_object_get_data (G_OBJECT (msg), "cancellable");
464
g_signal_handler_disconnect (cancellable, cancel_signal);
467
result = G_SIMPLE_ASYNC_RESULT (user_data);
469
if (msg->status_code != SOUP_STATUS_OK) {
470
parse_error (msg->status_code,
472
msg->response_body->data,
476
g_simple_async_result_complete (result);
477
g_object_unref (result);
481
message_cancel_cb (GCancellable *cancellable,
485
soup_session_cancel_message (g_object_get_data (G_OBJECT (msg), "session"),
486
msg, SOUP_STATUS_CANCELLED);
491
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
493
get_url_now (GrlNetWc *self,
495
GAsyncResult *result,
496
GCancellable *cancellable)
498
RequestResult *rr = g_slice_new0 (RequestResult);
500
g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
504
rr->request = soup_requester_request (self->priv->requester, url, NULL);
506
soup_request_send_async (rr->request, cancellable, reply_cb, result);
512
get_url_now (GrlNetWc *self,
514
GAsyncResult *result,
515
GCancellable *cancellable)
518
gulong cancel_signal;
520
msg = soup_message_new (SOUP_METHOD_GET, url);
523
g_simple_async_result_set_error (G_SIMPLE_ASYNC_RESULT (result),
525
GRL_NET_WC_ERROR_PROTOCOL_ERROR,
526
"Malformed URL: %s", url);
527
g_simple_async_result_complete_in_idle (G_SIMPLE_ASYNC_RESULT (result));
528
g_object_unref (result);
533
g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
538
g_object_set_data (G_OBJECT (msg),
541
cancel_signal = g_signal_connect (cancellable,
543
G_CALLBACK (message_cancel_cb),
547
g_object_set_data (G_OBJECT (msg),
549
GUINT_TO_POINTER (cancel_signal));
550
g_object_set_data_full (G_OBJECT (msg),
552
g_object_ref (self->priv->session),
555
soup_session_queue_message (self->priv->session,
275
struct request_clos {
278
GAsyncResult *result;
279
GCancellable *cancellable;
563
284
get_url_delayed (gpointer user_data)
565
RequestClosure *c, *d;
567
c = (RequestClosure *) user_data;
568
d = g_queue_pop_tail (c->self->priv->pending);
572
get_url_now (c->self,
574
G_ASYNC_RESULT (c->result),
286
struct request_clos *c = (struct request_clos *) user_data;
290
GrlNetWcPrivate *priv = c->self->priv;
291
struct request_clos *d = g_queue_pop_tail (priv->pending);
295
get_url_now (c->self, c->url, c->result, c->cancellable);
586
306
GAsyncResult *result,
587
307
GCancellable *cancellable)
311
struct request_clos *c;
312
GrlNetWcPrivate *priv = self->priv;
592
314
g_get_current_time (&now);
593
if (now.tv_sec - self->priv->last_request.tv_sec > self->priv->throttling) {
594
get_url_now (self, url, G_ASYNC_RESULT (result), cancellable);
595
g_get_current_time (&self->priv->last_request);
600
GRL_DEBUG ("delaying web request");
603
c = g_new (RequestClosure, 1);
605
c->url = g_strdup (url);
607
c->cancellable = cancellable;
609
self->priv->last_request.tv_sec += self->priv->throttling;
610
id = g_timeout_add_seconds (self->priv->last_request.tv_sec - now.tv_sec,
614
g_queue_push_head (self->priv->pending, c);
618
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
622
guint size_in_bytes = cache_size * 1024 * 1024;
623
soup_cache_set_max_size (cache, size_in_bytes);
627
cache_down (GrlNetWc *self)
629
soup_session_remove_feature (self->priv->session,
630
SOUP_SESSION_FEATURE (self->priv->cache));
631
g_object_unref (self->priv->cache);
632
self->priv->cache = NULL;
636
cache_up (GrlNetWc *self)
639
gchar *cache_dir = g_build_filename (g_get_user_cache_dir (),
643
cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
644
update_cache_size ();
648
self->priv->cache = g_object_ref (cache);
649
soup_session_add_feature (self->priv->session,
650
SOUP_SESSION_FEATURE (self->priv->cache));
316
if ((now.tv_sec - priv->last_request.tv_sec) > priv->throttling) {
317
get_url_now (self, url, result, cancellable);
318
g_get_current_time (&priv->last_request);
323
GRL_DEBUG ("delaying web request");
326
c = g_new (struct request_clos, 1);
328
c->url = g_strdup (url);
330
c->cancellable = cancellable;
332
priv->last_request.tv_sec += priv->throttling;
333
id = g_timeout_add_seconds (priv->last_request.tv_sec - now.tv_sec,
337
g_queue_push_head (self->priv->pending, c);
655
341
* grl_net_wc_new: