mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-30 02:58:03 +00:00
Allow allow downloading from a list of possible URLs
This commit is contained in:
parent
b8dfaccce7
commit
ddeceb419f
@ -33,4 +33,10 @@ void fwupd_client_update_metadata_stream_async(FwupdClient *self,
|
|||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer callback_data);
|
gpointer callback_data);
|
||||||
|
void fwupd_client_download_bytes2_async (FwupdClient *self,
|
||||||
|
GPtrArray *urls,
|
||||||
|
FwupdClientDownloadFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer callback_data);
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,6 +70,7 @@ typedef struct {
|
|||||||
|
|
||||||
#ifdef HAVE_LIBCURL
|
#ifdef HAVE_LIBCURL
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
GPtrArray *urls;
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
curl_mime *mime;
|
curl_mime *mime;
|
||||||
struct curl_slist *headers;
|
struct curl_slist *headers;
|
||||||
@ -118,6 +119,8 @@ fwupd_client_curl_helper_free (FwupdCurlHelper *helper)
|
|||||||
curl_mime_free (helper->mime);
|
curl_mime_free (helper->mime);
|
||||||
if (helper->headers != NULL)
|
if (helper->headers != NULL)
|
||||||
curl_slist_free_all (helper->headers);
|
curl_slist_free_all (helper->headers);
|
||||||
|
if (helper->urls != NULL)
|
||||||
|
g_ptr_array_unref (helper->urls);
|
||||||
g_free (helper);
|
g_free (helper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2473,7 +2476,7 @@ fwupd_client_install_release_download_cb (GObject *source, GAsyncResult *res, gp
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fwupd_client_is_url (const gchar *perhaps_url)
|
fwupd_client_is_url_http (const gchar *perhaps_url)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBCURL_7_62_0
|
#ifdef HAVE_LIBCURL_7_62_0
|
||||||
g_autoptr(CURLU) h = curl_url ();
|
g_autoptr(CURLU) h = curl_url ();
|
||||||
@ -2517,7 +2520,7 @@ fwupd_client_install_release_remote_cb (GObject *source, GAsyncResult *res, gpoi
|
|||||||
|
|
||||||
/* local and directory remotes may have the firmware already */
|
/* local and directory remotes may have the firmware already */
|
||||||
if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL &&
|
if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL &&
|
||||||
!fwupd_client_is_url (uri_tmp)) {
|
!fwupd_client_is_url_http (uri_tmp)) {
|
||||||
const gchar *fn_cache = fwupd_remote_get_filename_cache (remote);
|
const gchar *fn_cache = fwupd_remote_get_filename_cache (remote);
|
||||||
g_autofree gchar *path = g_path_get_dirname (fn_cache);
|
g_autofree gchar *path = g_path_get_dirname (fn_cache);
|
||||||
fn = g_build_filename (path, uri_tmp, NULL);
|
fn = g_build_filename (path, uri_tmp, NULL);
|
||||||
@ -4228,6 +4231,53 @@ fwupd_client_download_write_callback_cb (char *ptr, size_t size, size_t nmemb, v
|
|||||||
return realsize;
|
return realsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
fwupd_client_download_http (FwupdClient *self,
|
||||||
|
CURL *curl,
|
||||||
|
const gchar *url,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
CURLcode res;
|
||||||
|
gchar errbuf[CURL_ERROR_SIZE] = { '\0' };
|
||||||
|
g_autoptr(GByteArray) buf = g_byte_array_new ();
|
||||||
|
|
||||||
|
g_debug ("downloading %s", url);
|
||||||
|
fwupd_client_set_status (self, FWUPD_STATUS_DOWNLOADING);
|
||||||
|
curl_easy_setopt (curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
|
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, fwupd_client_download_write_callback_cb);
|
||||||
|
curl_easy_setopt (curl, CURLOPT_WRITEDATA, buf);
|
||||||
|
res = curl_easy_perform (curl);
|
||||||
|
fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
glong status_code = 0;
|
||||||
|
curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &status_code);
|
||||||
|
g_debug ("status-code was %ld", status_code);
|
||||||
|
if (status_code == 429) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"Failed to download due to server limit");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (errbuf[0] != '\0') {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"failed to download file: %s",
|
||||||
|
errbuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"failed to download file: %s",
|
||||||
|
curl_easy_strerror (res));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fwupd_client_download_bytes_thread_cb (GTask *task,
|
fwupd_client_download_bytes_thread_cb (GTask *task,
|
||||||
gpointer source_object,
|
gpointer source_object,
|
||||||
@ -4236,48 +4286,76 @@ fwupd_client_download_bytes_thread_cb (GTask *task,
|
|||||||
{
|
{
|
||||||
FwupdClient *self = FWUPD_CLIENT (source_object);
|
FwupdClient *self = FWUPD_CLIENT (source_object);
|
||||||
FwupdCurlHelper *helper = g_task_get_task_data (task);
|
FwupdCurlHelper *helper = g_task_get_task_data (task);
|
||||||
CURLcode res;
|
g_autoptr(GBytes) blob = NULL;
|
||||||
gchar errbuf[CURL_ERROR_SIZE] = { '\0' };
|
|
||||||
g_autoptr(GByteArray) buf = g_byte_array_new ();
|
|
||||||
|
|
||||||
curl_easy_setopt (helper->curl, CURLOPT_ERRORBUFFER, errbuf);
|
for (guint i = 0; i < helper->urls->len; i++) {
|
||||||
curl_easy_setopt (helper->curl, CURLOPT_WRITEFUNCTION, fwupd_client_download_write_callback_cb);
|
const gchar *url = g_ptr_array_index (helper->urls, i);
|
||||||
curl_easy_setopt (helper->curl, CURLOPT_WRITEDATA, buf);
|
g_autoptr(GError) error = NULL;
|
||||||
res = curl_easy_perform (helper->curl);
|
if (fwupd_client_is_url_http (url)) {
|
||||||
fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
|
blob = fwupd_client_download_http (self, helper->curl, url, &error);
|
||||||
if (res != CURLE_OK) {
|
if (blob != NULL)
|
||||||
glong status_code = 0;
|
break;
|
||||||
curl_easy_getinfo (helper->curl, CURLINFO_RESPONSE_CODE, &status_code);
|
} else {
|
||||||
g_debug ("status-code was %ld", status_code);
|
g_set_error (&error,
|
||||||
if (status_code == 429) {
|
FWUPD_ERROR,
|
||||||
g_task_return_new_error (task,
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
FWUPD_ERROR,
|
"not sure how to handle: %s", url);
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
}
|
||||||
"Failed to download due to server limit");
|
if (i == helper->urls->len - 1) {
|
||||||
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (errbuf[0] != '\0') {
|
g_warning ("failed to download %s: %s, trying next URI…",
|
||||||
g_task_return_new_error (task,
|
url, error->message);
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
|
||||||
"failed to download file: %s",
|
|
||||||
errbuf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_task_return_new_error (task,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INVALID_FILE,
|
|
||||||
"failed to download file: %s",
|
|
||||||
curl_easy_strerror (res));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
g_task_return_pointer (task,
|
g_task_return_pointer (task,
|
||||||
g_byte_array_free_to_bytes (g_steal_pointer (&buf)),
|
g_steal_pointer (&blob),
|
||||||
(GDestroyNotify) g_bytes_unref);
|
(GDestroyNotify) g_bytes_unref);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
void
|
||||||
|
fwupd_client_download_bytes2_async (FwupdClient *self,
|
||||||
|
GPtrArray *urls,
|
||||||
|
FwupdClientDownloadFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer callback_data)
|
||||||
|
{
|
||||||
|
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_autoptr(GTask) task = NULL;
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(FwupdCurlHelper) helper = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_return_if_fail (FWUPD_IS_CLIENT (self));
|
||||||
|
g_return_if_fail (urls != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
g_return_if_fail (priv->proxy != NULL);
|
||||||
|
|
||||||
|
/* ensure networking set up */
|
||||||
|
task = g_task_new (self, cancellable, callback, callback_data);
|
||||||
|
#ifdef HAVE_LIBCURL
|
||||||
|
helper = fwupd_client_curl_new (self, &error);
|
||||||
|
if (helper == NULL) {
|
||||||
|
g_task_return_error (task, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
helper->urls = g_ptr_array_ref (urls);
|
||||||
|
g_task_set_task_data (task, g_steal_pointer (&helper), (GDestroyNotify) fwupd_client_curl_helper_free);
|
||||||
|
|
||||||
|
/* download data */
|
||||||
|
g_task_run_in_thread (task, fwupd_client_download_bytes_thread_cb);
|
||||||
|
#else
|
||||||
|
g_task_return_new_error (task,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"no libcurl support");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fwupd_client_download_bytes_async:
|
* fwupd_client_download_bytes_async:
|
||||||
* @self: A #FwupdClient
|
* @self: A #FwupdClient
|
||||||
@ -4308,38 +4386,17 @@ fwupd_client_download_bytes_async (FwupdClient *self,
|
|||||||
gpointer callback_data)
|
gpointer callback_data)
|
||||||
{
|
{
|
||||||
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||||
g_autoptr(GTask) task = NULL;
|
g_autoptr(GPtrArray) urls = g_ptr_array_new_with_free_func (g_free);
|
||||||
#ifdef HAVE_LIBCURL
|
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
g_autoptr(FwupdCurlHelper) helper = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_return_if_fail (FWUPD_IS_CLIENT (self));
|
g_return_if_fail (FWUPD_IS_CLIENT (self));
|
||||||
g_return_if_fail (url != NULL);
|
g_return_if_fail (url != NULL);
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
g_return_if_fail (priv->proxy != NULL);
|
g_return_if_fail (priv->proxy != NULL);
|
||||||
|
|
||||||
/* ensure networking set up */
|
/* just proxy */
|
||||||
task = g_task_new (self, cancellable, callback, callback_data);
|
g_ptr_array_add (urls, g_strdup (url));
|
||||||
#ifdef HAVE_LIBCURL
|
fwupd_client_download_bytes2_async (self, urls, flags, cancellable,
|
||||||
helper = fwupd_client_curl_new (self, &error);
|
callback, callback_data);
|
||||||
if (helper == NULL) {
|
|
||||||
g_task_return_error (task, g_steal_pointer (&error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
curl_easy_setopt (helper->curl, CURLOPT_URL, url);
|
|
||||||
g_task_set_task_data (task, g_steal_pointer (&helper), (GDestroyNotify) fwupd_client_curl_helper_free);
|
|
||||||
|
|
||||||
/* download data */
|
|
||||||
g_debug ("downloading %s", url);
|
|
||||||
fwupd_client_set_status (self, FWUPD_STATUS_DOWNLOADING);
|
|
||||||
g_task_run_in_thread (task, fwupd_client_download_bytes_thread_cb);
|
|
||||||
#else
|
|
||||||
g_task_return_new_error (task,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_NOT_SUPPORTED,
|
|
||||||
"no libcurl support");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user