示例#1
0
static void
aws_s3_client_read_got_chunk (SoupMessage *message,
                              SoupBuffer  *buffer,
                              GTask       *task)
{
  AwsS3Client *client;
  ReadState *state;

  g_assert (SOUP_IS_MESSAGE (message));
  g_assert (buffer != NULL);
  g_assert (G_IS_TASK (task));

  client = g_task_get_source_object (task);
  g_assert (AWS_IS_S3_CLIENT (client));

  state = g_task_get_task_data (task);
  g_assert (state != NULL);
  g_assert (state->handler != NULL);

  if (!state->handler (client, message, buffer, state->handler_data))
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_CANCELLED,
                               "The request was cancelled");
      soup_session_cancel_message (SOUP_SESSION (client), message, SOUP_STATUS_CANCELLED);
   }
}
示例#2
0
static void
finalize (GObject *object)
{
	SoupSession *session = SOUP_SESSION (object);
	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);

	soup_message_queue_destroy (priv->queue);

	g_mutex_free (priv->host_lock);
	g_hash_table_destroy (priv->hosts);
	g_hash_table_destroy (priv->conns);

	g_free (priv->user_agent);

	if (priv->auth_manager)
		g_object_unref (priv->auth_manager);

	if (priv->ssl_creds)
		soup_ssl_free_client_credentials (priv->ssl_creds);

	if (priv->async_context)
		g_main_context_unref (priv->async_context);

	G_OBJECT_CLASS (soup_session_parent_class)->finalize (object);
}
示例#3
0
static void
run_queue (SoupSessionAsync *sa)
{
	SoupSession *session = SOUP_SESSION (sa);
	SoupMessageQueue *queue = soup_session_get_queue (session);
	SoupMessageQueueItem *item;
	SoupProxyURIResolver *proxy_resolver;
	SoupMessage *msg;
	SoupConnection *conn;
	gboolean try_pruning = TRUE, should_prune = FALSE;

	soup_session_cleanup_connections (session, FALSE);

 try_again:
	for (item = soup_message_queue_first (queue);
	     item && !should_prune;
	     item = soup_message_queue_next (queue, item)) {
		msg = item->msg;

		/* CONNECT messages are handled specially */
		if (msg->method == SOUP_METHOD_CONNECT)
			continue;

		if (soup_message_io_in_progress (msg))
			continue;

		if (!item->resolved_proxy_addr) {
			proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, msg);
			if (proxy_resolver) {
				resolve_proxy_addr (item, proxy_resolver);
				continue;
			} else
				item->resolved_proxy_addr = TRUE;
		}

		conn = soup_session_get_connection (session, item,
						    &should_prune);
		if (!conn)
			continue;

		if (soup_connection_get_state (conn) == SOUP_CONNECTION_NEW) {
			soup_connection_connect_async (conn, got_connection,
						       session);
		} else
			soup_session_send_queue_item (session, item, conn);
	}
	if (item)
		soup_message_queue_item_unref (item);

	if (try_pruning && should_prune) {
		/* There is at least one message in the queue that
		 * could be sent if we pruned an idle connection from
		 * some other server.
		 */
		if (soup_session_cleanup_connections (session, TRUE)) {
			try_pruning = should_prune = FALSE;
			goto try_again;
		}
	}
}
示例#4
0
static void
aws_s3_client_read_got_headers (SoupMessage *message,
                                GTask       *task)
{
  AwsS3Client *client;

  g_assert (SOUP_IS_MESSAGE(message));
  g_assert (G_IS_TASK (task));

  client = g_task_get_source_object (task);
  g_assert (AWS_IS_S3_CLIENT (client));

  if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code))
    {
      /*
       * Extract the given error type.
       */
      if (message->status_code == SOUP_STATUS_NOT_FOUND)
        {
          g_task_return_new_error (task,
                                   AWS_S3_CLIENT_ERROR,
                                   AWS_S3_CLIENT_ERROR_NOT_FOUND,
                                   "The requested object was not found.");
         soup_session_cancel_message (SOUP_SESSION (client), message, message->status_code);
        }
      else if (SOUP_STATUS_IS_CLIENT_ERROR (message->status_code))
        {
          g_task_return_new_error (task,
                                   AWS_S3_CLIENT_ERROR,
                                   AWS_S3_CLIENT_ERROR_BAD_REQUEST,
                                   "The request was invalid.");
          soup_session_cancel_message (SOUP_SESSION (client), message, message->status_code);
        }
      else
        {
          g_task_return_new_error (task,
                                   AWS_S3_CLIENT_ERROR,
                                   AWS_S3_CLIENT_ERROR_UNKNOWN,
                                   "An unknown error occurred.");
          soup_session_cancel_message (SOUP_SESSION (client), message, SOUP_STATUS_CANCELLED);
        }
    }
}
示例#5
0
static void
dispose (GObject *object)
{
	SoupSession *session = SOUP_SESSION (object);
	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);

	soup_session_abort (session);

	while (priv->features)
		soup_session_remove_feature (session, priv->features->data);

	G_OBJECT_CLASS (soup_session_parent_class)->dispose (object);
}
示例#6
0
/**
 * push_c2dm_client_deliver_async:
 * @client: A #PushC2dmClient.
 * @identity: A #PushC2dmIdentity.
 * @message: A #PushC2dmMessage.
 * @cancellable: (allow-none): A #GCancellable, or %NULL.
 * @callback: A callback to execute upon completion.
 * @user_data: User data for @callback.
 *
 * Requests that @message is pushed to the device identified by @identity.
 * Upon completion, @callback will be executed and is expected to call
 * push_c2dm_client_deliver_finish() to retrieve the result.
 */
void
push_c2dm_client_deliver_async (PushC2dmClient      *client,
                                PushC2dmIdentity    *identity,
                                PushC2dmMessage     *message,
                                GCancellable        *cancellable,
                                GAsyncReadyCallback  callback,
                                gpointer             user_data)
{
   PushC2dmClientPrivate *priv;
   GSimpleAsyncResult *simple;
   const gchar *auth_header;
   const gchar *registration_id;
   SoupMessage *request;
   GHashTable *params;

   ENTRY;

   g_return_if_fail(PUSH_IS_C2DM_CLIENT(client));
   g_return_if_fail(PUSH_IS_C2DM_IDENTITY(identity));
   g_return_if_fail(PUSH_IS_C2DM_MESSAGE(message));
   g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
   g_return_if_fail(callback);

   priv = client->priv;

   registration_id = push_c2dm_identity_get_registration_id(identity);
   params = push_c2dm_message_build_params(message);
   g_hash_table_insert(params,
                       g_strdup("registration_id"),
                       g_strdup(registration_id));
   request = soup_form_request_new_from_hash(SOUP_METHOD_POST,
                                             PUSH_C2DM_CLIENT_URL,
                                             params);
   auth_header = g_strdup_printf("GoogleLogin auth=%s", priv->auth_token);
   soup_message_headers_append(request->request_headers,
                               "Authorization",
                               auth_header);
   simple = g_simple_async_result_new(G_OBJECT(client), callback, user_data,
                                      push_c2dm_client_deliver_async);
   g_simple_async_result_set_check_cancellable(simple, cancellable);
   g_object_set_data_full(G_OBJECT(simple), "registration-id",
                          g_strdup(registration_id), g_free);
   soup_session_queue_message(SOUP_SESSION(client),
                              request,
                              push_c2dm_client_message_cb,
                              simple);
   g_hash_table_unref(params);

   EXIT;
}
示例#7
0
static void
get_property (GObject *object, guint prop_id,
	      GValue *value, GParamSpec *pspec)
{
	SoupSession *session = SOUP_SESSION (object);
	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);

	switch (prop_id) {
	case PROP_PROXY_URI:
		if (priv->proxy_resolver && SOUP_IS_PROXY_RESOLVER_STATIC (priv->proxy_resolver)) {
			g_object_get_property (G_OBJECT (priv->proxy_resolver),
					       SOUP_PROXY_RESOLVER_STATIC_PROXY_URI,
					       value);
		} else
			g_value_set_boxed (value, NULL);
		break;
	case PROP_MAX_CONNS:
		g_value_set_int (value, priv->max_conns);
		break;
	case PROP_MAX_CONNS_PER_HOST:
		g_value_set_int (value, priv->max_conns_per_host);
		break;
	case PROP_USE_NTLM:
		g_object_get_property (G_OBJECT (priv->auth_manager),
				       SOUP_AUTH_MANAGER_NTLM_USE_NTLM,
				       value);
		break;
	case PROP_SSL_CA_FILE:
		g_value_set_string (value, priv->ssl_ca_file);
		break;
	case PROP_ASYNC_CONTEXT:
		g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
		break;
	case PROP_TIMEOUT:
		g_value_set_uint (value, priv->io_timeout);
		break;
	case PROP_USER_AGENT:
		g_value_set_string (value, priv->user_agent);
		break;
	case PROP_IDLE_TIMEOUT:
		g_value_set_uint (value, priv->idle_timeout);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
示例#8
0
static void
run_queue (SoupSessionAsync *sa)
{
	SoupSession *session = SOUP_SESSION (sa);
	SoupMessageQueue *queue = soup_session_get_queue (session);
	SoupMessageQueueItem *item;
	SoupMessage *msg;
	gboolean try_pruning = TRUE, should_prune = FALSE;

	g_object_ref (session);
	soup_session_cleanup_connections (session, FALSE);

 try_again:
	for (item = soup_message_queue_first (queue);
	     item && !should_prune;
	     item = soup_message_queue_next (queue, item)) {
		msg = item->msg;

		/* CONNECT messages are handled specially */
		if (msg->method != SOUP_METHOD_CONNECT)
			process_queue_item (item, &should_prune, TRUE);
	}
	if (item)
		soup_message_queue_item_unref (item);

	if (try_pruning && should_prune) {
		/* There is at least one message in the queue that
		 * could be sent if we pruned an idle connection from
		 * some other server.
		 */
		if (soup_session_cleanup_connections (session, TRUE)) {
			try_pruning = should_prune = FALSE;
			goto try_again;
		}
	}

	g_object_unref (session);
}
static void
send_message_cb(GObject* source,
    GAsyncResult* res, gpointer udata)
{
    RETURN_IF_FAIL(SOUP_IS_SESSION(source));
    RETURN_IF_FAIL(G_IS_ASYNC_RESULT(res));
    RETURN_IF_FAIL(udata != NULL);

    ResourceData* data = udata;
    GtResourceDownloader* self = GT_RESOURCE_DOWNLOADER(data->self);
    GtResourceDownloaderPrivate* priv = gt_resource_downloader_get_instance_private(self);
    g_autoptr(GError) err = NULL;

    data->istream = soup_session_send_finish(SOUP_SESSION(source), res, &err);

    if (!err)
        g_thread_pool_push(dl_pool, data, NULL);
    else
    {
        data->cb(NULL, data->udata, g_steal_pointer(&err));
        resource_data_free(data);
    }
}
示例#10
0
/**
 * push_gcm_client_deliver_async:
 * @client: (in): A #PushGcmClient.
 * @identities: (element-type PushGcmIdentity*): A #GList of #PushGcmIdentity.
 * @message: A #PushGcmMessage.
 * @cancellable: (allow-none): A #GCancellable or %NULL.
 * @callback: A #GAsyncReadyCallback.
 * @user_data: User data for @callback.
 *
 * Asynchronously deliver a #PushGcmMessage to one or more GCM enabled
 * devices.
 */
void
push_gcm_client_deliver_async (PushGcmClient       *client,
                               GList               *identities,
                               PushGcmMessage      *message,
                               GCancellable        *cancellable,
                               GAsyncReadyCallback  callback,
                               gpointer             user_data)
{
   PushGcmClientPrivate *priv;
   GSimpleAsyncResult *simple;
   SoupMessage *request;
   const gchar *registration_id;
   const gchar *collapse_key;
   JsonGenerator *g;
   JsonObject *obj;
   JsonObject *data;
   JsonObject *mdata;
   JsonArray *ar;
   JsonNode *node;
   GList *iter;
   GList *list;
   gchar *str;
   gsize length;
   guint time_to_live;

   ENTRY;

   g_return_if_fail(PUSH_IS_GCM_CLIENT(client));
   g_return_if_fail(identities);
   g_return_if_fail(PUSH_IS_GCM_MESSAGE(message));
   g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable));
   g_return_if_fail(callback);

   priv = client->priv;

   request = soup_message_new("POST", PUSH_GCM_CLIENT_URL);
   ar = json_array_new();

   for (iter = identities; iter; iter = iter->next) {
      g_assert(PUSH_IS_GCM_IDENTITY(iter->data));
      registration_id = push_gcm_identity_get_registration_id(iter->data);
      json_array_add_string_element(ar, registration_id);
   }

   str = g_strdup_printf("key=%s", priv->auth_token);
   soup_message_headers_append(request->request_headers, "Authorization", str);
   g_free(str);

   soup_message_headers_append(request->request_headers,
                               "Accept",
                               "application/json");

   data = json_object_new();

   if ((collapse_key = push_gcm_message_get_collapse_key(message))) {
      json_object_set_string_member(data, "collapse_key", collapse_key);
   }

   json_object_set_boolean_member(data,
                                  "delay_while_idle",
                                  push_gcm_message_get_delay_while_idle(message));

   json_object_set_boolean_member(data,
                                  "dry_run",
                                  push_gcm_message_get_dry_run(message));

   if ((time_to_live = push_gcm_message_get_time_to_live(message))) {
      json_object_set_int_member(data, "time_to_live", time_to_live);
   }

   if ((mdata = push_gcm_message_get_data(message))) {
      json_object_set_object_member(data, "data", mdata);
   }

   obj = json_object_new();
   json_object_set_array_member(obj, "registration_ids", ar);
   json_object_set_object_member(obj, "data", data);

   node = json_node_new(JSON_NODE_OBJECT);
   json_node_set_object(node, obj);
   json_object_unref(obj);

   g = json_generator_new();
   json_generator_set_pretty(g, TRUE);
   json_generator_set_indent(g, 2);
   json_generator_set_root(g, node);
   str = json_generator_to_data(g, &length);
   json_node_free(node);
   g_object_unref(g);

   g_print("REQUEST: \"%s\"\n", str);

   soup_message_set_request(request,
                            "application/json",
                            SOUP_MEMORY_TAKE,
                            str,
                            length);

   simple = g_simple_async_result_new(G_OBJECT(client), callback, user_data,
                                      push_gcm_client_deliver_async);

   /*
    * Keep the list of identities around until we receive our result.
    * We need them to key with the resulting array.
    */
   list = g_list_copy(identities);
   g_list_foreach(list, (GFunc)g_object_ref, NULL);
   g_object_set_data_full(G_OBJECT(simple),
                          "identities",
                          list,
                          _push_gcm_identities_free);

   soup_session_queue_message(SOUP_SESSION(client),
                              request,
                              push_gcm_client_deliver_cb,
                              simple);

   EXIT;
}
示例#11
0
static void
set_property (GObject *object, guint prop_id,
	      const GValue *value, GParamSpec *pspec)
{
	SoupSession *session = SOUP_SESSION (object);
	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
	SoupURI *uri;
	gboolean ca_file_changed = FALSE;
	const char *new_ca_file, *user_agent;

	switch (prop_id) {
	case PROP_PROXY_URI:
		uri = g_value_get_boxed (value);

		if (uri) {
			soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER);
			priv->proxy_resolver = SOUP_PROXY_URI_RESOLVER (soup_proxy_resolver_static_new (uri));
			soup_session_add_feature (session, SOUP_SESSION_FEATURE (priv->proxy_resolver));
			g_object_unref (priv->proxy_resolver);
		} else if (priv->proxy_resolver && SOUP_IS_PROXY_RESOLVER_STATIC (priv->proxy_resolver))
			soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER);

		soup_session_abort (session);
		break;
	case PROP_MAX_CONNS:
		priv->max_conns = g_value_get_int (value);
		break;
	case PROP_MAX_CONNS_PER_HOST:
		priv->max_conns_per_host = g_value_get_int (value);
		break;
	case PROP_USE_NTLM:
		g_object_set_property (G_OBJECT (priv->auth_manager),
				       SOUP_AUTH_MANAGER_NTLM_USE_NTLM,
				       value);
		break;
	case PROP_SSL_CA_FILE:
		new_ca_file = g_value_get_string (value);

		if (!safe_str_equal (priv->ssl_ca_file, new_ca_file))
			ca_file_changed = TRUE;

		g_free (priv->ssl_ca_file);
		priv->ssl_ca_file = g_strdup (new_ca_file);

		if (ca_file_changed && priv->ssl_creds) {
			soup_ssl_free_client_credentials (priv->ssl_creds);
			priv->ssl_creds = NULL;
		}

		break;
	case PROP_ASYNC_CONTEXT:
		priv->async_context = g_value_get_pointer (value);
		if (priv->async_context)
			g_main_context_ref (priv->async_context);
		break;
	case PROP_TIMEOUT:
		priv->io_timeout = g_value_get_uint (value);
		break;
	case PROP_USER_AGENT:
		g_free (priv->user_agent);
		user_agent = g_value_get_string (value);
		if (!user_agent)
			priv->user_agent = NULL;
		else if (!*user_agent) {
			priv->user_agent =
				g_strdup (SOUP_SESSION_USER_AGENT_BASE);
		} else if (g_str_has_suffix (user_agent, " ")) {
			priv->user_agent =
				g_strdup_printf ("%s%s", user_agent,
						 SOUP_SESSION_USER_AGENT_BASE);
		} else
			priv->user_agent = g_strdup (user_agent);
		break;
	case PROP_IDLE_TIMEOUT:
		priv->idle_timeout = g_value_get_uint (value);
		break;
	case PROP_ADD_FEATURE:
		soup_session_add_feature (session, g_value_get_object (value));
		break;
	case PROP_ADD_FEATURE_BY_TYPE:
		soup_session_add_feature_by_type (session, g_value_get_gtype (value));
		break;
	case PROP_REMOVE_FEATURE_BY_TYPE:
		soup_session_remove_feature_by_type (session, g_value_get_gtype (value));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
示例#12
0
void
aws_s3_client_read_async (AwsS3Client            *client,
                          const gchar            *bucket,
                          const gchar            *path,
                          AwsS3ClientDataHandler  handler,
                          gpointer                handler_data,
                          GDestroyNotify          handler_notify,
                          GCancellable           *cancellable,
                          GAsyncReadyCallback     callback,
                          gpointer                user_data)
{
  AwsS3ClientPrivate *priv = aws_s3_client_get_instance_private (client);
  g_autoptr(GTask) task = NULL;
  g_autofree gchar *auth = NULL;
  g_autofree gchar *date_str = NULL;
  g_autofree gchar *signature = NULL;
  g_autofree gchar *uri = NULL;
  g_autoptr(SoupDate) date = NULL;
  g_autoptr(GString) str = NULL;
  g_autoptr(SoupMessage) message = NULL;
  ReadState *state;
  guint16 port;

  g_return_if_fail (AWS_IS_S3_CLIENT(client));
  g_return_if_fail (bucket);
  g_return_if_fail (path);
  g_return_if_fail (g_utf8_validate(bucket, -1, NULL));
  g_return_if_fail (g_utf8_validate(path, -1, NULL));
  g_return_if_fail (handler != NULL);

  task = g_task_new (client, cancellable, callback, user_data);
  g_task_set_source_tag (task, aws_s3_client_read_async);

  state = read_state_new (handler, handler_data, handler_notify);
  g_task_set_task_data (task, state, read_state_free);

  /*
   * Strip leading '/' from the path.
   */
  while (g_utf8_get_char (path) == '/')
    path = g_utf8_next_char (path);

  /*
   * Determine our connection port.
   */
  port = priv->port_set ? priv->port : (priv->secure ? 443 : 80);

  /*
   * Build our HTTP request message.
   */
  uri = g_strdup_printf ("%s://%s:%d/%s/%s",
                         priv->secure ? "https" : "http",
                         priv->host,
                         port,
                         bucket,
                         path);
  message = soup_message_new (SOUP_METHOD_GET, uri);
  soup_message_body_set_accumulate (message->response_body, FALSE);
  g_signal_connect_object (message,
                           "got-chunk",
                           G_CALLBACK (aws_s3_client_read_got_chunk),
                           task,
                           0);
  g_signal_connect_object (message,
                           "got-headers",
                           G_CALLBACK (aws_s3_client_read_got_headers),
                           task,
                           0);

  /*
   * Set the Host header for systems that may be proxying.
   */
  if (priv->host != NULL)
    soup_message_headers_append (message->request_headers, "Host", priv->host);

  /*
   * Add the Date header which we need for signing.
   */
  date = soup_date_new_from_now (0);
  date_str = soup_date_to_string (date, SOUP_DATE_HTTP);
  soup_message_headers_append (message->request_headers, "Date", date_str);

  /*
   * Sign our request.
   */
  str = g_string_new ("GET\n\n\n");
  g_string_append_printf (str, "%s\n", date_str);
  g_string_append_printf (str, "/%s/%s", bucket, path);
  signature = aws_credentials_sign (priv->creds, str->str, str->len, G_CHECKSUM_SHA1);

  /*
   * Attach request signature to our headers.
   */
  auth = g_strdup_printf ("AWS %s:%s",
                          aws_credentials_get_access_key (priv->creds),
                          signature);
  soup_message_headers_append (message->request_headers, "Authorization", auth);

  /*
   * Submit our request to the target.
   */
  soup_session_queue_message (SOUP_SESSION (client),
                              g_steal_pointer (&message),
                              aws_s3_client_read_cb,
                              g_steal_pointer (&task));
}
示例#13
0
static void
catch_resource_group_api_fetch_async (CatchResourceGroup  *group,
                                      guint                index_,
                                      guint                count,
                                      GAsyncReadyCallback  callback,
                                      gpointer             user_data)
{
   CatchResourceGroupPrivate *priv;
   CatchMessageBuilder *builder;
   GSimpleAsyncResult *simple;
   SoupMessage *message;
   const gchar *space = NULL; /* TODO */

   ENTRY;

   g_return_if_fail(CATCH_IS_RESOURCE_GROUP(group));
   g_return_if_fail(callback != NULL);

   priv = group->priv;

   g_assert(priv->resource_type);
   g_assert(priv->session);

   if (count && ((index_ + count) > priv->count)) {
      count = priv->count - index_;
   }

   /*
    * If we can satisfy the request immediately, do so.
    */
   if (priv->first_page_size && priv->first_page_size >= (index_ + count)) {
      simple = g_simple_async_result_new(G_OBJECT(group), callback, user_data,
                                         catch_resource_group_fetch_async);
      g_simple_async_result_set_op_res_gboolean(simple, TRUE);
      g_simple_async_result_complete_in_idle(simple);
      g_object_unref(simple);
      EXIT;
   }

   /*
    * Ignore the first page of results if we have already fetched them.
    */
   if (!index_) {
      index_ = priv->first_page_size;
      count -= priv->first_page_size;
   }

   simple = g_simple_async_result_new(G_OBJECT(group), callback, user_data,
                                      catch_resource_group_fetch_async);
   g_object_set_data(G_OBJECT(simple), "index", GINT_TO_POINTER(index_));
   g_object_set_data(G_OBJECT(simple), "count", GINT_TO_POINTER(count));

   builder = catch_resource_group_get_builder(group);

   if (index_) {
      catch_message_builder_add_int_param(builder, "offset", index_);
   }

   if (count) {
      catch_message_builder_add_int_param(builder, "limit", count);
   }

   /*
    * TODO: Filtering.
    */
#if 0
   filter = catch_resource_group_get_filter(set);

   if (filter && (search_query = catch_resource_filter_get_search_query(filter))) {
      catch_message_builder_add_string_param(builder, "q", search_query);
   }

   if (filter && (sma = catch_resource_filter_get_server_modified_at(filter))) {
      catch_message_builder_add_string_param(builder, "server_modified_at$gte", sma);
   }
#endif

   /*
    * TODO: If the whole range doesn't come back on our request, we should pump
    *       the next request.
    */

   if (g_type_is_a(priv->resource_type, CATCH_TYPE_SPACE)) {
      catch_message_builder_set_path(builder, "v3", "streams", NULL);
   } else if (g_type_is_a(priv->resource_type, CATCH_TYPE_OBJECT)) {
#if 0
      if (filter) {
         if ((spaces = catch_resource_filter_get_spaces(filter))) {
            space = spaces[0];
         }
      }
#endif
      catch_message_builder_set_path(builder, "v3", "streams",
                                     space ? space : "sync",
                                     NULL);
   } else if (g_type_is_a(priv->resource_type, CATCH_TYPE_ACTIVITY)) {
      catch_message_builder_set_path(builder, "v3", "activities", NULL);
   } else {
      g_assert_not_reached();
   }

   message = catch_message_builder_build(builder);
   soup_session_queue_message(SOUP_SESSION(priv->session), message,
                              catch_resource_group_api_fetch_cb,
                              simple);
   catch_message_builder_unref(builder);

   EXIT;
}
示例#14
0
static void
catch_resource_group_api_fetch_cb (SoupSession *session,
                                   SoupMessage *message,
                                   gpointer     user_data)
{
   CatchResourceGroupPrivate *priv;
   CatchMessageBuilder *builder;
   GSimpleAsyncResult *simple = user_data;
   CatchResourceGroup *group;
   const gchar *uri;
   JsonNode *node = NULL;
   GError *error = NULL;
   guint offset;
   guint n_resources;
   guint count;
   guint index_;

   ENTRY;

   g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple));
   group = CATCH_RESOURCE_GROUP(g_async_result_get_source_object(user_data));
   g_return_if_fail(CATCH_IS_RESOURCE_GROUP(group));

   priv = group->priv;

   if (!(node = catch_resource_group_api_parse_response(group, message, &error))) {
      g_simple_async_result_take_error(simple, error);
      GOTO(finish);
   }

   if (g_type_is_a(priv->resource_type, CATCH_TYPE_SPACE)) {
      if (!catch_resource_group_api_parse_spaces(group, node, &offset, &n_resources, &error)) {
         g_simple_async_result_take_error(simple, error);
         GOTO(finish);
      }
      g_simple_async_result_set_op_res_gboolean(simple, TRUE);
   } else if (g_type_is_a(priv->resource_type, CATCH_TYPE_OBJECT)) {
      if (!catch_resource_group_api_parse_objects(group, node, &offset, &n_resources, &error)) {
         g_simple_async_result_take_error(simple, error);
         GOTO(finish);
      }
      g_simple_async_result_set_op_res_gboolean(simple, TRUE);
   } else if (g_type_is_a(priv->resource_type, CATCH_TYPE_ACTIVITY)) {
      if (!catch_resource_group_api_parse_activities(group, node, &offset, &n_resources, &error)) {
         g_simple_async_result_take_error(simple, error);
         GOTO(finish);
      }
      g_simple_async_result_set_op_res_gboolean(simple, TRUE);
   } else {
      g_assert_not_reached();
   }

   /*
    * If we did not satisfy the range of items to load on this query, we need
    * to start another one.
    */
   count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(simple), "count"));
   index_ = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(simple), "index"));

   if ((offset + n_resources) < (index_ + count)) {
      offset += n_resources;
      builder = catch_resource_group_get_builder(group);
      catch_message_builder_add_int_param(builder, "offset", offset);
      uri = soup_uri_get_path(soup_message_get_uri(message));
      catch_message_builder_set_path(builder, uri, NULL);
      message = catch_message_builder_build(builder);
      /*
       * TODO: Limit range to what we need, rather than server max.
       */
      soup_session_queue_message(SOUP_SESSION(priv->session), message,
                                 catch_resource_group_api_fetch_cb,
                                 simple);
      catch_message_builder_unref(builder);
      if (node) {
         json_node_free(node);
      }
      EXIT;
   }

   g_simple_async_result_set_op_res_gboolean(simple, TRUE);

finish:
   if (node) {
      json_node_free(node);
   }
   g_simple_async_result_complete_in_idle(simple);
   g_object_unref(simple);

   EXIT;
}