mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-04 01:20:25 +00:00
Switch from libsoup to libcurl
The former drags on glib-networking and then gsettings-desktop-schemas, which add over 5Mb to the minimal IoT and CoreOS composes. Everything already uses libcurl (even NetworkManager!) and so this is an easy way to reduce image size.
This commit is contained in:
parent
a6e6085365
commit
3a73c342ba
@ -32,14 +32,16 @@ jobs:
|
||||
gcc
|
||||
gcab
|
||||
mingw32-nsis
|
||||
mingw64-brotli
|
||||
mingw64-gcc
|
||||
mingw64-pkg-config
|
||||
mingw64-glib2
|
||||
mingw64-gnutls
|
||||
mingw64-libgusb
|
||||
mingw64-sqlite
|
||||
mingw64-libarchive
|
||||
mingw64-json-glib
|
||||
mingw64-libsoup
|
||||
mingw64-curl
|
||||
wine
|
||||
- checkout
|
||||
- run:
|
||||
|
@ -11,7 +11,7 @@ license=('GPL2')
|
||||
depends=('libgusb' 'modemmanager' 'tpm2-tss')
|
||||
makedepends=('meson' 'valgrind' 'gobject-introspection' 'gtk-doc' 'python-pillow' 'git'
|
||||
'python-cairo' 'noto-fonts' 'noto-fonts-cjk' 'python-gobject' 'vala'
|
||||
'libsoup' 'polkit' 'gcab')
|
||||
'curl' 'polkit' 'gcab')
|
||||
|
||||
pkgver() {
|
||||
cd ${pkgname}
|
||||
|
@ -817,20 +817,20 @@
|
||||
<package variant="x86_64" />
|
||||
</distro>
|
||||
</dependency>
|
||||
<dependency type="build" id="libsoup2.4-dev">
|
||||
<dependency type="build" id="libcurl4-gnutls-dev">
|
||||
<distro id="arch">
|
||||
<package>libsoup</package>
|
||||
<package>curl</package>
|
||||
</distro>
|
||||
<distro id="centos">
|
||||
<package>libsoup-devel</package>
|
||||
<package>libcurl-devel</package>
|
||||
</distro>
|
||||
<distro id="fedora">
|
||||
<package>libsoup-devel</package>
|
||||
<package>libcurl-devel</package>
|
||||
</distro>
|
||||
<distro id="debian">
|
||||
<control />
|
||||
<package variant="x86_64" />
|
||||
<package variant="s390x">libsoup2.4-dev:s390x</package>
|
||||
<package variant="s390x">libcurl4-gnutls-dev:s390x</package>
|
||||
<package variant="i386" />
|
||||
</distro>
|
||||
<distro id="ubuntu">
|
||||
|
@ -1,7 +1,7 @@
|
||||
%global glib2_version 2.45.8
|
||||
%global libxmlb_version 0.1.3
|
||||
%global libgusb_version 0.3.5
|
||||
%global libsoup_version 2.51.92
|
||||
%global libcurl_version 7.62.0
|
||||
%global libjcat_version 0.1.0
|
||||
%global systemd_version 231
|
||||
%global json_glib_version 1.1.1
|
||||
@ -55,7 +55,7 @@ BuildRequires: libxmlb-devel >= %{libxmlb_version}
|
||||
BuildRequires: libgcab1-devel
|
||||
BuildRequires: libgudev1-devel
|
||||
BuildRequires: libgusb-devel >= %{libgusb_version}
|
||||
BuildRequires: libsoup-devel >= %{libsoup_version}
|
||||
BuildRequires: libcurl-devel >= %{libcurl_version}
|
||||
BuildRequires: libjcat-devel >= %{libjcat_version}
|
||||
BuildRequires: polkit-devel >= 0.103
|
||||
BuildRequires: sqlite-devel
|
||||
@ -112,7 +112,6 @@ Requires(postun): systemd
|
||||
Requires: glib2%{?_isa} >= %{glib2_version}
|
||||
Requires: libxmlb%{?_isa} >= %{libxmlb_version}
|
||||
Requires: libgusb%{?_isa} >= %{libgusb_version}
|
||||
Requires: libsoup%{?_isa} >= %{libsoup_version}
|
||||
Requires: bubblewrap
|
||||
Requires: shared-mime-info
|
||||
|
||||
|
@ -48,7 +48,7 @@ Section "fwupd"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libnettle-7.dll"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libp11-kit-0.dll"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libpcre-1.dll"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libsoup-2.4-1.dll"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libcurl-4.dll"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libsqlite3-0.dll"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libtasn1-6.dll"
|
||||
File "/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libusb-1.0.dll"
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
#include <libsoup/soup.h>
|
||||
#include <curl/curl.h>
|
||||
#ifdef HAVE_GIO_UNIX
|
||||
#include <gio/gunixfdlist.h>
|
||||
#endif
|
||||
@ -52,10 +52,14 @@ typedef struct {
|
||||
gchar *host_security_id;
|
||||
GDBusConnection *conn;
|
||||
GDBusProxy *proxy;
|
||||
SoupSession *soup_session;
|
||||
gchar *user_agent;
|
||||
} FwupdClientPrivate;
|
||||
|
||||
typedef struct {
|
||||
CURL *curl;
|
||||
curl_mime *mime;
|
||||
} FwupdCurlHelper;
|
||||
|
||||
enum {
|
||||
SIGNAL_CHANGED,
|
||||
SIGNAL_STATUS_CHANGED,
|
||||
@ -71,7 +75,7 @@ enum {
|
||||
PROP_PERCENTAGE,
|
||||
PROP_DAEMON_VERSION,
|
||||
PROP_TAINTED,
|
||||
PROP_SOUP_SESSION,
|
||||
PROP_SOUP_SESSION, /* unused ABI */
|
||||
PROP_HOST_PRODUCT,
|
||||
PROP_HOST_MACHINE_ID,
|
||||
PROP_HOST_SECURITY_ID,
|
||||
@ -84,6 +88,20 @@ static guint signals [SIGNAL_LAST] = { 0 };
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (FwupdClient, fwupd_client, G_TYPE_OBJECT)
|
||||
#define GET_PRIVATE(o) (fwupd_client_get_instance_private (o))
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURLU, curl_url_cleanup)
|
||||
|
||||
static void
|
||||
fwupd_client_curl_helper_free (FwupdCurlHelper *helper)
|
||||
{
|
||||
if (helper->curl != NULL)
|
||||
curl_easy_cleanup (helper->curl);
|
||||
if (helper->mime != NULL)
|
||||
curl_mime_free (helper->mime);
|
||||
g_free (helper);
|
||||
}
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FwupdCurlHelper, fwupd_client_curl_helper_free)
|
||||
|
||||
static void
|
||||
fwupd_client_set_host_product (FwupdClient *self, const gchar *host_product)
|
||||
{
|
||||
@ -262,12 +280,6 @@ gboolean
|
||||
fwupd_client_ensure_networking (FwupdClient *self, GError **error)
|
||||
{
|
||||
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||
const gchar *http_proxy;
|
||||
g_autoptr(SoupSession) session = NULL;
|
||||
|
||||
/* already exists */
|
||||
if (priv->soup_session != NULL)
|
||||
return TRUE;
|
||||
|
||||
/* check the user agent is sane */
|
||||
if (priv->user_agent == NULL) {
|
||||
@ -284,22 +296,62 @@ fwupd_client_ensure_networking (FwupdClient *self, GError **error)
|
||||
"user agent unsuitable; fwupd version required");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* create the soup session */
|
||||
session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT, priv->user_agent,
|
||||
SOUP_SESSION_TIMEOUT, 60,
|
||||
NULL);
|
||||
if (session == NULL) {
|
||||
static int
|
||||
fwupd_client_progress_callback_cb (void *clientp,
|
||||
curl_off_t dltotal,
|
||||
curl_off_t dlnow,
|
||||
curl_off_t ultotal,
|
||||
curl_off_t ulnow)
|
||||
{
|
||||
FwupdClient *self = FWUPD_CLIENT (clientp);
|
||||
|
||||
/* calculate percentage */
|
||||
if (dltotal > 0 && dlnow >= 0 && dlnow <= dltotal) {
|
||||
guint percentage = (guint) ((100 * dlnow) / dltotal);
|
||||
g_debug ("download progress: %u%%", percentage);
|
||||
fwupd_client_set_percentage (self, percentage);
|
||||
} else if (ultotal > 0 && ulnow >= 0 && ulnow <= ultotal) {
|
||||
guint percentage = (guint) ((100 * ulnow) / ultotal);
|
||||
g_debug ("upload progress: %u%%", percentage);
|
||||
fwupd_client_set_percentage (self, percentage);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FwupdCurlHelper *
|
||||
fwupd_client_curl_new (FwupdClient *self, GError **error)
|
||||
{
|
||||
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||
const gchar *http_proxy;
|
||||
g_autoptr(FwupdCurlHelper) helper = g_new0 (FwupdCurlHelper, 1);
|
||||
|
||||
/* check the user agent is sane */
|
||||
if (!fwupd_client_ensure_networking (self, error))
|
||||
return NULL;
|
||||
|
||||
/* create the session */
|
||||
helper->curl = curl_easy_init ();
|
||||
if (helper->curl == NULL) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INTERNAL,
|
||||
"failed to setup networking");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
if (g_getenv ("FWUPD_CURL_VERBOSE") != NULL)
|
||||
curl_easy_setopt (helper->curl, CURLOPT_VERBOSE, 1L);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_XFERINFOFUNCTION, fwupd_client_progress_callback_cb);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_XFERINFODATA, self);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_USERAGENT, priv->user_agent);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_CONNECTTIMEOUT, 60L);
|
||||
|
||||
/* relax the SSL checks for broken corporate proxies */
|
||||
if (g_getenv ("DISABLE_SSL_STRICT") != NULL)
|
||||
g_object_set (session, SOUP_SESSION_SSL_STRICT, FALSE, NULL);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
|
||||
/* set the proxy */
|
||||
http_proxy = g_getenv ("https_proxy");
|
||||
@ -309,22 +361,12 @@ fwupd_client_ensure_networking (FwupdClient *self, GError **error)
|
||||
http_proxy = g_getenv ("http_proxy");
|
||||
if (http_proxy == NULL)
|
||||
http_proxy = g_getenv ("HTTP_PROXY");
|
||||
if (http_proxy != NULL && strlen (http_proxy) > 0) {
|
||||
g_autoptr(SoupURI) proxy_uri = soup_uri_new (http_proxy);
|
||||
if (proxy_uri == NULL) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INTERNAL,
|
||||
"invalid proxy URI: %s", http_proxy);
|
||||
return FALSE;
|
||||
}
|
||||
g_object_set (session, SOUP_SESSION_PROXY_URI, proxy_uri, NULL);
|
||||
}
|
||||
if (http_proxy != NULL && strlen (http_proxy) > 0)
|
||||
curl_easy_setopt (helper->curl, CURLOPT_PROXY, http_proxy);
|
||||
|
||||
/* this disables the double-compression of the firmware.xml.gz file */
|
||||
soup_session_remove_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER);
|
||||
priv->soup_session = g_steal_pointer (&session);
|
||||
return TRUE;
|
||||
curl_easy_setopt (helper->curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
|
||||
return g_steal_pointer (&helper);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2234,6 +2276,13 @@ fwupd_client_install_release_download_cb (GObject *source, GAsyncResult *res, gp
|
||||
g_steal_pointer (&task));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fwupd_client_is_url (const gchar *perhaps_url)
|
||||
{
|
||||
g_autoptr(CURLU) h = curl_url ();
|
||||
return curl_url_set (h, CURLUPART_URL, perhaps_url, 0) == CURLUE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
fwupd_client_install_release_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
@ -2242,7 +2291,6 @@ fwupd_client_install_release_remote_cb (GObject *source, GAsyncResult *res, gpoi
|
||||
g_autoptr(FwupdRemote) remote = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = G_TASK (user_data);
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
FwupdClientInstallReleaseData *data = g_task_get_task_data (task);
|
||||
GCancellable *cancellable = g_task_get_cancellable (task);
|
||||
|
||||
@ -2254,8 +2302,8 @@ fwupd_client_install_release_remote_cb (GObject *source, GAsyncResult *res, gpoi
|
||||
}
|
||||
|
||||
/* local and directory remotes may have the firmware already */
|
||||
uri = soup_uri_new (fwupd_release_get_uri (data->release));
|
||||
if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL && uri == NULL) {
|
||||
if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL &&
|
||||
!fwupd_client_is_url (fwupd_release_get_uri (data->release))) {
|
||||
const gchar *fn_cache = fwupd_remote_get_filename_cache (remote);
|
||||
g_autofree gchar *path = g_path_get_dirname (fn_cache);
|
||||
fn = g_build_filename (path, fwupd_release_get_uri (data->release), NULL);
|
||||
@ -3929,97 +3977,60 @@ fwupd_client_set_user_agent_for_package (FwupdClient *self,
|
||||
priv->user_agent = g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
fwupd_client_download_chunk_cb (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
|
||||
static size_t
|
||||
fwupd_client_download_write_callback_cb (char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
guint percentage;
|
||||
goffset header_size;
|
||||
goffset body_length;
|
||||
FwupdClient *self = FWUPD_CLIENT (user_data);
|
||||
|
||||
/* if it's returning "Found" or an error, ignore the percentage */
|
||||
if (msg->status_code != SOUP_STATUS_OK) {
|
||||
g_debug ("ignoring status code %u (%s)",
|
||||
msg->status_code, msg->reason_phrase);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get data */
|
||||
body_length = msg->response_body->length;
|
||||
header_size = soup_message_headers_get_content_length (msg->response_headers);
|
||||
if (header_size < body_length)
|
||||
return;
|
||||
|
||||
/* calculate percentage */
|
||||
percentage = (guint) ((100 * body_length) / header_size);
|
||||
g_debug ("progress: %u%%", percentage);
|
||||
fwupd_client_set_percentage (self, percentage);
|
||||
GByteArray *buf = (GByteArray *) userdata;
|
||||
gsize realsize = size * nmemb;
|
||||
g_byte_array_append (buf, (const guint8 *) ptr, realsize);
|
||||
return realsize;
|
||||
}
|
||||
|
||||
static void
|
||||
fwupd_client_read_bytes_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
fwupd_client_download_bytes_thread_cb (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = G_TASK (user_data);
|
||||
FwupdClient *self = FWUPD_CLIENT (source_object);
|
||||
FwupdCurlHelper *helper = g_task_get_task_data (task);
|
||||
CURLcode res;
|
||||
gchar errbuf[CURL_ERROR_SIZE] = { '\0' };
|
||||
g_autoptr(GByteArray) buf = g_byte_array_new ();
|
||||
|
||||
bytes = fwupd_input_stream_read_bytes_finish (G_INPUT_STREAM (source), res, &error);
|
||||
if (bytes == NULL) {
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
/* success */
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&bytes),
|
||||
(GDestroyNotify) g_bytes_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
fwupd_client_download_bytes_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = G_TASK (user_data);
|
||||
FwupdClient *self = g_task_get_source_object (task);
|
||||
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||
GCancellable *cancellable = g_task_get_cancellable (task);
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GInputStream) istr = NULL;
|
||||
guint status_code = 0;
|
||||
SoupMessage *msg = g_task_get_task_data (task);
|
||||
|
||||
/* get the result */
|
||||
curl_easy_setopt (helper->curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_WRITEFUNCTION, fwupd_client_download_write_callback_cb);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_WRITEDATA, buf);
|
||||
res = curl_easy_perform (helper->curl);
|
||||
fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
|
||||
istr = soup_session_send_finish (priv->soup_session, res, &error);
|
||||
if (istr == NULL) {
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
/* check the input stream before reading the data */
|
||||
g_object_get (msg, "status-code", &status_code, NULL);
|
||||
g_debug ("status-code was %u", status_code);
|
||||
if (status_code == 429) {
|
||||
if (res != CURLE_OK) {
|
||||
glong status_code = 0;
|
||||
curl_easy_getinfo (helper->curl, CURLINFO_RESPONSE_CODE, &status_code);
|
||||
g_debug ("status-code was %ld", status_code);
|
||||
if (status_code == 429) {
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to download due to server limit");
|
||||
return;
|
||||
}
|
||||
if (errbuf[0] != '\0') {
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"%s", errbuf);
|
||||
return;
|
||||
}
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to download due to server limit");
|
||||
return;
|
||||
}
|
||||
if (status_code != SOUP_STATUS_OK) {
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to download: %s",
|
||||
soup_status_get_phrase (status_code));
|
||||
return;
|
||||
}
|
||||
"%s", curl_easy_strerror (res));
|
||||
|
||||
/* read the input stream into a GBytes, async */
|
||||
fwupd_input_stream_read_bytes_async (istr, cancellable,
|
||||
fwupd_client_read_bytes_cb,
|
||||
g_steal_pointer (&task));
|
||||
return;
|
||||
}
|
||||
g_task_return_pointer (task,
|
||||
g_byte_array_free_to_bytes (g_steal_pointer (&buf)),
|
||||
(GDestroyNotify) g_bytes_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4049,9 +4060,8 @@ fwupd_client_download_bytes_async (FwupdClient *self,
|
||||
{
|
||||
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||
g_autoptr(GTask) task = NULL;
|
||||
g_autoptr(SoupMessage) msg = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FwupdCurlHelper) helper = NULL;
|
||||
|
||||
g_return_if_fail (FWUPD_IS_CLIENT (self));
|
||||
g_return_if_fail (url != NULL);
|
||||
@ -4060,31 +4070,18 @@ fwupd_client_download_bytes_async (FwupdClient *self,
|
||||
|
||||
/* ensure networking set up */
|
||||
task = g_task_new (self, cancellable, callback, callback_data);
|
||||
if (!fwupd_client_ensure_networking (self, &error)) {
|
||||
helper = fwupd_client_curl_new (self, &error);
|
||||
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);
|
||||
uri = soup_uri_new (url);
|
||||
msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
|
||||
if (msg == NULL) {
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to parse URI %s", url);
|
||||
return;
|
||||
}
|
||||
g_signal_connect (msg, "got-chunk",
|
||||
G_CALLBACK (fwupd_client_download_chunk_cb),
|
||||
self);
|
||||
g_task_set_task_data (task, g_object_ref (msg), (GDestroyNotify) g_object_unref);
|
||||
fwupd_client_set_status (self, FWUPD_STATUS_DOWNLOADING);
|
||||
soup_session_send_async (priv->soup_session, msg,
|
||||
cancellable,
|
||||
fwupd_client_download_bytes_cb,
|
||||
g_steal_pointer (&task));
|
||||
g_task_run_in_thread (task, fwupd_client_download_bytes_thread_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4109,42 +4106,43 @@ fwupd_client_download_bytes_finish (FwupdClient *self, GAsyncResult *res, GError
|
||||
}
|
||||
|
||||
static void
|
||||
fwupd_client_upload_bytes_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
fwupd_client_upload_bytes_thread_cb (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autoptr(GTask) task = G_TASK (user_data);
|
||||
FwupdClient *self = g_task_get_source_object (task);
|
||||
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||
GCancellable *cancellable = g_task_get_cancellable (task);
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GInputStream) istr = NULL;
|
||||
guint status_code;
|
||||
SoupMessage *msg = g_task_get_task_data (task);
|
||||
FwupdClient *self = FWUPD_CLIENT (source_object);
|
||||
FwupdCurlHelper *helper = g_task_get_task_data (task);
|
||||
CURLcode res;
|
||||
gchar errbuf[CURL_ERROR_SIZE] = { '\0' };
|
||||
g_autoptr(GByteArray) buf = g_byte_array_new ();
|
||||
|
||||
/* get the result */
|
||||
istr = soup_session_send_finish (priv->soup_session, res, &error);
|
||||
if (istr == NULL) {
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
/* check the input stream before reading the data */
|
||||
g_object_get (msg, "status-code", &status_code, NULL);
|
||||
g_debug ("status-code was %u", status_code);
|
||||
if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) {
|
||||
curl_easy_setopt (helper->curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_WRITEFUNCTION, fwupd_client_download_write_callback_cb);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_WRITEDATA, buf);
|
||||
res = curl_easy_perform (helper->curl);
|
||||
fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
|
||||
if (res != CURLE_OK) {
|
||||
glong status_code = 0;
|
||||
curl_easy_getinfo (helper->curl, CURLINFO_RESPONSE_CODE, &status_code);
|
||||
g_debug ("status-code was %ld", status_code);
|
||||
if (errbuf[0] != '\0') {
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"%s", errbuf);
|
||||
return;
|
||||
}
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to download: %s",
|
||||
soup_status_get_phrase (status_code));
|
||||
"%s", curl_easy_strerror (res));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* read the input stream into a GBytes, async */
|
||||
fwupd_input_stream_read_bytes_async (istr, cancellable,
|
||||
fwupd_client_read_bytes_cb,
|
||||
g_steal_pointer (&task));
|
||||
g_task_return_pointer (task,
|
||||
g_byte_array_free_to_bytes (g_steal_pointer (&buf)),
|
||||
(GDestroyNotify) g_bytes_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4178,8 +4176,7 @@ fwupd_client_upload_bytes_async (FwupdClient *self,
|
||||
{
|
||||
FwupdClientPrivate *priv = GET_PRIVATE (self);
|
||||
g_autoptr(GTask) task = NULL;
|
||||
g_autoptr(SoupMessage) msg = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
g_autoptr(FwupdCurlHelper) helper = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
g_return_if_fail (FWUPD_IS_CLIENT (self));
|
||||
@ -4189,48 +4186,37 @@ fwupd_client_upload_bytes_async (FwupdClient *self,
|
||||
|
||||
/* ensure networking set up */
|
||||
task = g_task_new (self, cancellable, callback, callback_data);
|
||||
if (!fwupd_client_ensure_networking (self, &error)) {
|
||||
helper = fwupd_client_curl_new (self, &error);
|
||||
if (helper == NULL) {
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
/* download data */
|
||||
g_debug ("downloading %s", url);
|
||||
uri = soup_uri_new (url);
|
||||
|
||||
/* build message */
|
||||
if ((flags & FWUPD_CLIENT_UPLOAD_FLAG_ALWAYS_MULTIPART) > 0 ||
|
||||
signature != NULL) {
|
||||
g_autoptr(SoupMultipart) mp = NULL;
|
||||
mp = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
|
||||
soup_multipart_append_form_string (mp, "payload", payload);
|
||||
if (signature != NULL)
|
||||
soup_multipart_append_form_string (mp, "signature", signature);
|
||||
msg = soup_form_request_new_from_multipart (url, mp);
|
||||
curl_mimepart *part;
|
||||
helper->mime = curl_mime_init (helper->curl);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_MIMEPOST, helper->mime);
|
||||
part = curl_mime_addpart (helper->mime);
|
||||
curl_mime_data (part, payload, CURL_ZERO_TERMINATED);
|
||||
curl_mime_name (part, "payload");
|
||||
if (signature != NULL) {
|
||||
part = curl_mime_addpart (helper->mime);
|
||||
curl_mime_data (part, signature, CURL_ZERO_TERMINATED);
|
||||
curl_mime_name (part, "signature");
|
||||
}
|
||||
} else {
|
||||
msg = soup_message_new (SOUP_METHOD_POST, url);
|
||||
soup_message_set_request (msg, "application/json; charset=utf-8",
|
||||
SOUP_MEMORY_COPY, payload, strlen (payload));
|
||||
curl_easy_setopt (helper->mime, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt (helper->curl, CURLOPT_POSTFIELDSIZE, strlen (payload));
|
||||
curl_easy_setopt (helper->curl, CURLOPT_COPYPOSTFIELDS, payload);
|
||||
}
|
||||
|
||||
/* POST request */
|
||||
if (msg == NULL) {
|
||||
g_task_return_new_error (task,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to parse URI %s", url);
|
||||
return;
|
||||
}
|
||||
g_signal_connect (msg, "got-chunk",
|
||||
G_CALLBACK (fwupd_client_download_chunk_cb),
|
||||
self);
|
||||
g_task_set_task_data (task, g_object_ref (msg), (GDestroyNotify) g_object_unref);
|
||||
fwupd_client_set_status (self, FWUPD_STATUS_IDLE);
|
||||
g_debug ("uploading to %s", url);
|
||||
soup_session_send_async (priv->soup_session, msg,
|
||||
cancellable,
|
||||
fwupd_client_upload_bytes_cb,
|
||||
g_steal_pointer (&task));
|
||||
curl_easy_setopt (helper->curl, CURLOPT_URL, url);
|
||||
g_task_set_task_data (task, g_steal_pointer (&helper), (GDestroyNotify) fwupd_client_curl_helper_free);
|
||||
g_task_run_in_thread (task, fwupd_client_upload_bytes_thread_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4269,7 +4255,7 @@ fwupd_client_get_property (GObject *object, guint prop_id,
|
||||
g_value_set_boolean (value, priv->tainted);
|
||||
break;
|
||||
case PROP_SOUP_SESSION:
|
||||
g_value_set_object (value, priv->soup_session);
|
||||
g_value_set_object (value, NULL);
|
||||
break;
|
||||
case PROP_PERCENTAGE:
|
||||
g_value_set_uint (value, priv->percentage);
|
||||
@ -4309,9 +4295,6 @@ fwupd_client_set_property (GObject *object, guint prop_id,
|
||||
case PROP_PERCENTAGE:
|
||||
priv->percentage = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_SOUP_SESSION:
|
||||
g_set_object (&priv->soup_session, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -4471,12 +4454,12 @@ fwupd_client_class_init (FwupdClientClass *klass)
|
||||
/**
|
||||
* FwupdClient:soup-session:
|
||||
*
|
||||
* The libsoup session.
|
||||
* The libsoup session, now unused.
|
||||
*
|
||||
* Since: 1.4.5
|
||||
*/
|
||||
pspec = g_param_spec_object ("soup-session", NULL, NULL, SOUP_TYPE_SESSION,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
|
||||
pspec = g_param_spec_object ("soup-session", NULL, NULL, G_TYPE_OBJECT,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_NAME);
|
||||
g_object_class_install_property (object_class, PROP_SOUP_SESSION, pspec);
|
||||
|
||||
/**
|
||||
@ -4533,8 +4516,6 @@ fwupd_client_finalize (GObject *object)
|
||||
g_object_unref (priv->conn);
|
||||
if (priv->proxy != NULL)
|
||||
g_object_unref (priv->proxy);
|
||||
if (priv->soup_session != NULL)
|
||||
g_object_unref (priv->soup_session);
|
||||
|
||||
G_OBJECT_CLASS (fwupd_client_parent_class)->finalize (object);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libsoup/soup.h>
|
||||
#include <curl/curl.h>
|
||||
#include <jcat.h>
|
||||
|
||||
#include "fwupd-deprecated.h"
|
||||
@ -67,6 +67,10 @@ enum {
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (FwupdRemote, fwupd_remote, G_TYPE_OBJECT)
|
||||
#define GET_PRIVATE(o) (fwupd_remote_get_instance_private (o))
|
||||
|
||||
typedef gchar curlptr;
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(curlptr, curl_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURLU, curl_url_cleanup)
|
||||
|
||||
static void
|
||||
fwupd_remote_set_username (FwupdRemote *self, const gchar *username)
|
||||
{
|
||||
@ -150,11 +154,11 @@ fwupd_remote_set_filename_source (FwupdRemote *self, const gchar *filename_sourc
|
||||
priv->filename_source = g_strdup (filename_source);
|
||||
}
|
||||
|
||||
static SoupURI *
|
||||
static CURLU *
|
||||
fwupd_remote_build_uri (FwupdRemote *self, const gchar *url, GError **error)
|
||||
{
|
||||
FwupdRemotePrivate *priv = GET_PRIVATE (self);
|
||||
SoupURI *uri;
|
||||
g_autoptr(CURLU) uri = curl_url ();
|
||||
|
||||
g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
|
||||
g_return_val_if_fail (url != NULL, NULL);
|
||||
@ -162,48 +166,43 @@ fwupd_remote_build_uri (FwupdRemote *self, const gchar *url, GError **error)
|
||||
|
||||
/* create URI, substituting if required */
|
||||
if (priv->firmware_base_uri != NULL) {
|
||||
g_autoptr(SoupURI) uri_tmp = NULL;
|
||||
g_autofree gchar *basename = NULL;
|
||||
g_autofree gchar *url2 = NULL;
|
||||
uri_tmp = soup_uri_new (url);
|
||||
if (uri_tmp == NULL) {
|
||||
g_autofree gchar *path_new = NULL;
|
||||
g_autoptr(curlptr) path = NULL;
|
||||
g_autoptr(CURLU) uri_tmp = curl_url ();
|
||||
if (curl_url_set (uri_tmp, CURLUPART_URL, url, 0) != CURLUE_OK) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to parse URI '%s'", url);
|
||||
return NULL;
|
||||
}
|
||||
basename = g_path_get_basename (soup_uri_get_path (uri_tmp));
|
||||
url2 = g_build_filename (priv->firmware_base_uri, basename, NULL);
|
||||
uri = soup_uri_new (url2);
|
||||
if (uri == NULL) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to parse URI '%s'", url2);
|
||||
"Failed to parse url '%s'", url);
|
||||
return NULL;
|
||||
}
|
||||
curl_url_get (uri_tmp, CURLUPART_PATH, &path, 0);
|
||||
basename = g_path_get_basename (path);
|
||||
path_new = g_build_filename (priv->firmware_base_uri, basename, NULL);
|
||||
curl_url_set (uri, CURLUPART_URL, path_new, 0);
|
||||
|
||||
/* use the base URI of the metadata to build the full path */
|
||||
} else if (g_strstr_len (url, -1, "/") == NULL) {
|
||||
g_autofree gchar *basename = NULL;
|
||||
g_autofree gchar *path = NULL;
|
||||
uri = soup_uri_new (priv->metadata_uri);
|
||||
if (uri == NULL) {
|
||||
g_autofree gchar *path_new = NULL;
|
||||
g_autoptr(curlptr) path = NULL;
|
||||
if (curl_url_set (uri, CURLUPART_URL, priv->metadata_uri, 0) != CURLUE_OK) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"Failed to parse metadata URI '%s'", url);
|
||||
"Failed to parse url '%s'",
|
||||
priv->metadata_uri);
|
||||
return NULL;
|
||||
}
|
||||
basename = g_path_get_dirname (soup_uri_get_path (uri));
|
||||
path = g_build_filename (basename, url, NULL);
|
||||
soup_uri_set_path (uri, path);
|
||||
curl_url_get (uri, CURLUPART_PATH, &path, 0);
|
||||
basename = g_path_get_dirname (path);
|
||||
path_new = g_build_filename (basename, url, NULL);
|
||||
curl_url_set (uri, CURLUPART_URL, path_new, 0);
|
||||
|
||||
/* a normal URI */
|
||||
} else {
|
||||
uri = soup_uri_new (url);
|
||||
if (uri == NULL) {
|
||||
if (curl_url_set (uri, CURLUPART_URL, url, 0) != CURLUE_OK) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
@ -214,10 +213,10 @@ fwupd_remote_build_uri (FwupdRemote *self, const gchar *url, GError **error)
|
||||
|
||||
/* set the username and password */
|
||||
if (priv->username != NULL)
|
||||
soup_uri_set_user (uri, priv->username);
|
||||
curl_url_set (uri, CURLUPART_USER, priv->username, 0);
|
||||
if (priv->password != NULL)
|
||||
soup_uri_set_password (uri, priv->password);
|
||||
return uri;
|
||||
curl_url_set (uri, CURLUPART_PASSWORD, priv->password, 0);
|
||||
return g_steal_pointer (&uri);
|
||||
}
|
||||
|
||||
/* note, this has to be set before username and password */
|
||||
@ -225,12 +224,6 @@ static void
|
||||
fwupd_remote_set_metadata_uri (FwupdRemote *self, const gchar *metadata_uri)
|
||||
{
|
||||
FwupdRemotePrivate *priv = GET_PRIVATE (self);
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
|
||||
/* build the URI */
|
||||
uri = soup_uri_new (metadata_uri);
|
||||
if (uri == NULL)
|
||||
return;
|
||||
|
||||
/* save this so we can export the object as a GVariant */
|
||||
priv->metadata_uri = g_strdup (metadata_uri);
|
||||
@ -872,10 +865,12 @@ fwupd_remote_get_checksum (FwupdRemote *self)
|
||||
gchar *
|
||||
fwupd_remote_build_firmware_uri (FwupdRemote *self, const gchar *url, GError **error)
|
||||
{
|
||||
g_autoptr(SoupURI) uri = fwupd_remote_build_uri (self, url, error);
|
||||
g_autoptr(curlptr) tmp = NULL;
|
||||
g_autoptr(CURLU) uri = fwupd_remote_build_uri (self, url, error);
|
||||
if (uri == NULL)
|
||||
return NULL;
|
||||
return soup_uri_to_string (uri, FALSE);
|
||||
curl_url_get (uri, CURLUPART_URL, &tmp, 0);
|
||||
return g_strdup (tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ install_headers([
|
||||
|
||||
libfwupd_deps = [
|
||||
giounix,
|
||||
soup,
|
||||
libcurl,
|
||||
libjcat,
|
||||
libjsonglib,
|
||||
]
|
||||
@ -122,19 +122,18 @@ if get_option('introspection')
|
||||
header : 'fwupd.h',
|
||||
dependencies : [
|
||||
giounix,
|
||||
soup,
|
||||
libcurl,
|
||||
],
|
||||
includes : [
|
||||
'Gio-2.0',
|
||||
'GObject-2.0',
|
||||
'Soup-2.4',
|
||||
],
|
||||
install : true
|
||||
)
|
||||
|
||||
gnome.generate_vapi('fwupd',
|
||||
sources : fwupd_gir[0],
|
||||
packages : ['gio-2.0', 'libsoup-2.4'],
|
||||
packages : ['gio-2.0'],
|
||||
install : true,
|
||||
)
|
||||
|
||||
@ -178,7 +177,7 @@ if get_option('tests')
|
||||
],
|
||||
dependencies : [
|
||||
gio,
|
||||
soup,
|
||||
libcurl,
|
||||
libjsonglib,
|
||||
],
|
||||
link_with : fwupd,
|
||||
|
@ -143,7 +143,6 @@ fwupdplugin_pkgg.generate(
|
||||
'json-glib-1.0',
|
||||
'libarchive',
|
||||
'libgcab-1.0',
|
||||
'libsoup-2.4',
|
||||
'xmlb',
|
||||
'jcat',
|
||||
],
|
||||
|
@ -208,7 +208,7 @@ endif
|
||||
libjcat = dependency('jcat', version : '>= 0.1.0', fallback : ['libjcat', 'libjcat_dep'])
|
||||
libjsonglib = dependency('json-glib-1.0', version : '>= 1.1.1')
|
||||
valgrind = dependency('valgrind', required: false)
|
||||
soup = dependency('libsoup-2.4', version : '>= 2.51.92')
|
||||
libcurl = dependency('libcurl', version : '>= 7.62.0')
|
||||
if build_daemon
|
||||
if get_option('polkit')
|
||||
polkit = dependency('polkit-gobject-1', version : '>= 0.103')
|
||||
@ -448,7 +448,6 @@ if build_standalone
|
||||
plugin_deps += giounix
|
||||
plugin_deps += gmodule
|
||||
plugin_deps += gusb
|
||||
plugin_deps += soup
|
||||
plugin_deps += libarchive
|
||||
plugin_deps += gudev
|
||||
plugin_deps += libjsonglib
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
#include <libsoup/soup.h>
|
||||
#include <curl/curl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fwupd-error.h"
|
||||
@ -22,14 +22,11 @@
|
||||
struct _FuRedfishClient
|
||||
{
|
||||
GObject parent_instance;
|
||||
SoupSession *session;
|
||||
CURL *curl;
|
||||
gchar *hostname;
|
||||
guint port;
|
||||
gchar *username;
|
||||
gchar *password;
|
||||
gchar *update_uri_path;
|
||||
gchar *push_uri_path;
|
||||
gboolean auth_created;
|
||||
gboolean use_https;
|
||||
gboolean cacheck;
|
||||
GPtrArray *devices;
|
||||
@ -37,62 +34,57 @@ struct _FuRedfishClient
|
||||
|
||||
G_DEFINE_TYPE (FuRedfishClient, fu_redfish_client, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
fu_redfish_client_set_auth (FuRedfishClient *self, SoupURI *uri,
|
||||
SoupMessage *msg)
|
||||
typedef gchar curlptr;
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(curlptr, curl_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURLU, curl_url_cleanup)
|
||||
|
||||
static size_t
|
||||
fu_redfish_client_fetch_data_cb (char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
{
|
||||
if ((self->username != NULL && self->password != NULL) &&
|
||||
self->auth_created == FALSE) {
|
||||
/*
|
||||
* Some redfish implementations miss WWW-Authenticate
|
||||
* header for a 401 response, and SoupAuthManager couldn't
|
||||
* generate SoupAuth accordingly. Since DSP0266 makes
|
||||
* Basic Authorization a requirement for redfish, it shall be
|
||||
* safe to use Basic Auth for all redfish implementations.
|
||||
*/
|
||||
SoupAuthManager *manager = SOUP_AUTH_MANAGER (soup_session_get_feature (self->session, SOUP_TYPE_AUTH_MANAGER));
|
||||
g_autoptr(SoupAuth) auth = soup_auth_new (SOUP_TYPE_AUTH_BASIC,
|
||||
msg, "Basic");
|
||||
soup_auth_authenticate (auth, self->username, self->password);
|
||||
soup_auth_manager_use_auth (manager, uri, auth);
|
||||
self->auth_created = TRUE;
|
||||
}
|
||||
GByteArray *buf = (GByteArray *) userdata;
|
||||
gsize realsize = size * nmemb;
|
||||
g_byte_array_append (buf, (const guint8 *) ptr, realsize);
|
||||
return realsize;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
fu_redfish_client_fetch_data (FuRedfishClient *self, const gchar *uri_path, GError **error)
|
||||
{
|
||||
guint status_code;
|
||||
g_autoptr(SoupMessage) msg = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
CURLcode res;
|
||||
g_autofree gchar *port = g_strdup_printf ("%u", self->port);
|
||||
g_autoptr(CURLU) uri = NULL;
|
||||
g_autoptr(GByteArray) buf = g_byte_array_new ();
|
||||
|
||||
/* create URI */
|
||||
uri = soup_uri_new (NULL);
|
||||
soup_uri_set_scheme (uri, self->use_https ? "https" : "http");
|
||||
soup_uri_set_path (uri, uri_path);
|
||||
soup_uri_set_host (uri, self->hostname);
|
||||
soup_uri_set_port (uri, self->port);
|
||||
msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
|
||||
if (msg == NULL) {
|
||||
g_autofree gchar *tmp = soup_uri_to_string (uri, FALSE);
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"failed to create message for URI %s", tmp);
|
||||
uri = curl_url ();
|
||||
curl_url_set (uri, CURLU_DEFAULT_SCHEME, self->use_https ? "https" : "http", 0);
|
||||
curl_url_set (uri, CURLUPART_PATH, uri_path, 0);
|
||||
curl_url_set (uri, CURLUPART_HOST, self->hostname, 0);
|
||||
curl_url_set (uri, CURLUPART_PORT, port, 0);
|
||||
if (curl_easy_setopt (self->curl, CURLOPT_CURLU, uri) != CURLE_OK) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"failed to create message for URI");
|
||||
return NULL;
|
||||
}
|
||||
fu_redfish_client_set_auth (self, uri, msg);
|
||||
status_code = soup_session_send_message (self->session, msg);
|
||||
if (status_code != SOUP_STATUS_OK) {
|
||||
g_autofree gchar *tmp = soup_uri_to_string (uri, FALSE);
|
||||
curl_easy_setopt (self->curl, CURLOPT_WRITEFUNCTION, fu_redfish_client_fetch_data_cb);
|
||||
curl_easy_setopt (self->curl, CURLOPT_WRITEDATA, buf);
|
||||
res = curl_easy_perform (self->curl);
|
||||
if (res != CURLE_OK) {
|
||||
glong status_code = 0;
|
||||
g_autoptr(curlptr) uri_str = NULL;
|
||||
curl_easy_getinfo (self->curl, CURLINFO_RESPONSE_CODE, &status_code);
|
||||
curl_url_get (uri, CURLUPART_URL, &uri_str, 0);
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"failed to download %s: %s",
|
||||
tmp, soup_status_get_phrase (status_code));
|
||||
uri_str, curl_easy_strerror (res));
|
||||
return NULL;
|
||||
}
|
||||
return g_bytes_new (msg->response_body->data, msg->response_body->length);
|
||||
|
||||
return g_byte_array_free_to_bytes (g_steal_pointer (&buf));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -569,19 +561,19 @@ fu_redfish_client_set_smbios_interfaces (FuRedfishClient *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(curl_mime, curl_mime_free)
|
||||
|
||||
gboolean
|
||||
fu_redfish_client_update (FuRedfishClient *self, FuDevice *device, GBytes *blob_fw,
|
||||
GError **error)
|
||||
{
|
||||
CURLcode res;
|
||||
FwupdRelease *release;
|
||||
curl_mimepart *part;
|
||||
g_autofree gchar *filename = NULL;
|
||||
|
||||
guint status_code;
|
||||
g_autoptr(SoupMessage) msg = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
g_autoptr(SoupMultipart) multipart = NULL;
|
||||
g_autoptr(SoupBuffer) buffer = NULL;
|
||||
g_autofree gchar *uri_str = NULL;
|
||||
g_autofree gchar *port = g_strdup_printf ("%u", self->port);
|
||||
g_autoptr(CURLU) uri = curl_url ();
|
||||
g_autoptr(curl_mime) mime = curl_mime_init (self->curl);
|
||||
|
||||
/* Get the update version */
|
||||
release = fwupd_device_get_release_default (FWUPD_DEVICE (device));
|
||||
@ -595,38 +587,35 @@ fu_redfish_client_update (FuRedfishClient *self, FuDevice *device, GBytes *blob_
|
||||
}
|
||||
|
||||
/* create URI */
|
||||
uri = soup_uri_new (NULL);
|
||||
soup_uri_set_scheme (uri, self->use_https ? "https" : "http");
|
||||
soup_uri_set_path (uri, self->push_uri_path);
|
||||
soup_uri_set_host (uri, self->hostname);
|
||||
soup_uri_set_port (uri, self->port);
|
||||
uri_str = soup_uri_to_string (uri, FALSE);
|
||||
|
||||
/* Create the multipart request */
|
||||
multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
|
||||
buffer = soup_buffer_new (SOUP_MEMORY_COPY,
|
||||
g_bytes_get_data (blob_fw, NULL),
|
||||
g_bytes_get_size (blob_fw));
|
||||
soup_multipart_append_form_file (multipart, filename, filename,
|
||||
"application/octet-stream",
|
||||
buffer);
|
||||
msg = soup_form_request_new_from_multipart (uri_str, multipart);
|
||||
if (msg == NULL) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"failed to create message for URI %s", uri_str);
|
||||
curl_url_set (uri, CURLU_DEFAULT_SCHEME, self->use_https ? "https" : "http", 0);
|
||||
curl_url_set (uri, CURLUPART_PATH, self->push_uri_path, 0);
|
||||
curl_url_set (uri, CURLUPART_HOST, self->hostname, 0);
|
||||
curl_url_set (uri, CURLUPART_PORT, port, 0);
|
||||
if (curl_easy_setopt (self->curl, CURLOPT_CURLU, uri) != CURLE_OK) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"failed to create message for URI");
|
||||
return FALSE;
|
||||
}
|
||||
fu_redfish_client_set_auth (self, uri, msg);
|
||||
status_code = soup_session_send_message (self->session, msg);
|
||||
if (status_code != SOUP_STATUS_OK) {
|
||||
|
||||
/* Create the multipart request */
|
||||
curl_easy_setopt (self->curl, CURLOPT_MIMEPOST, mime);
|
||||
part = curl_mime_addpart (mime);
|
||||
curl_mime_data (part, g_bytes_get_data (blob_fw, NULL), g_bytes_get_size (blob_fw));
|
||||
curl_mime_type (part, "application/octet-stream");
|
||||
res = curl_easy_perform (self->curl);
|
||||
if (res != CURLE_OK) {
|
||||
glong status_code = 0;
|
||||
g_autoptr(curlptr) uri_str = NULL;
|
||||
curl_easy_getinfo (self->curl, CURLINFO_RESPONSE_CODE, &status_code);
|
||||
curl_url_get (uri, CURLUPART_URL, &uri_str, 0);
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INVALID_FILE,
|
||||
"failed to upload %s to %s: %s",
|
||||
filename, uri_str,
|
||||
soup_status_get_phrase (status_code));
|
||||
curl_easy_strerror (res));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -662,24 +651,12 @@ fu_redfish_client_setup (FuRedfishClient *self, GBytes *smbios_table, GError **e
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* create the soup session */
|
||||
/* setup networking */
|
||||
user_agent = g_strdup_printf ("%s/%s", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
self->session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT, user_agent,
|
||||
SOUP_SESSION_TIMEOUT, 60,
|
||||
NULL);
|
||||
if (self->session == NULL) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INTERNAL,
|
||||
"failed to setup networking");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->cacheck == FALSE) {
|
||||
g_object_set (G_OBJECT (self->session),
|
||||
SOUP_SESSION_SSL_STRICT, FALSE,
|
||||
NULL);
|
||||
}
|
||||
curl_easy_setopt (self->curl, CURLOPT_USERAGENT , user_agent);
|
||||
curl_easy_setopt (self->curl, CURLOPT_CONNECTTIMEOUT, 60L);
|
||||
if (self->cacheck == FALSE)
|
||||
curl_easy_setopt (self->curl, CURLOPT_SSL_VERIFYPEER , 0L);
|
||||
|
||||
/* this is optional */
|
||||
if (smbios_table != NULL) {
|
||||
@ -700,10 +677,6 @@ fu_redfish_client_setup (FuRedfishClient *self, GBytes *smbios_table, GError **e
|
||||
g_debug ("Hostname: %s", self->hostname);
|
||||
if (self->port != 0)
|
||||
g_debug ("Port: %u", self->port);
|
||||
if (self->username != NULL)
|
||||
g_debug ("Username: %s", self->username);
|
||||
if (self->password != NULL)
|
||||
g_debug ("Password: %s", self->password);
|
||||
|
||||
/* try to connect */
|
||||
blob = fu_redfish_client_fetch_data (self, "/redfish/v1/", error);
|
||||
@ -800,28 +773,24 @@ fu_redfish_client_set_cacheck (FuRedfishClient *self, gboolean cacheck)
|
||||
void
|
||||
fu_redfish_client_set_username (FuRedfishClient *self, const gchar *username)
|
||||
{
|
||||
g_free (self->username);
|
||||
self->username = g_strdup (username);
|
||||
curl_easy_setopt (self->curl, CURLOPT_USERNAME, username);
|
||||
}
|
||||
|
||||
void
|
||||
fu_redfish_client_set_password (FuRedfishClient *self, const gchar *password)
|
||||
{
|
||||
g_free (self->password);
|
||||
self->password = g_strdup (password);
|
||||
curl_easy_setopt (self->curl, CURLOPT_PASSWORD, password);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_redfish_client_finalize (GObject *object)
|
||||
{
|
||||
FuRedfishClient *self = FU_REDFISH_CLIENT (object);
|
||||
if (self->session != NULL)
|
||||
g_object_unref (self->session);
|
||||
if (self->curl != NULL)
|
||||
curl_easy_cleanup (self->curl);
|
||||
g_free (self->update_uri_path);
|
||||
g_free (self->push_uri_path);
|
||||
g_free (self->hostname);
|
||||
g_free (self->username);
|
||||
g_free (self->password);
|
||||
g_ptr_array_unref (self->devices);
|
||||
G_OBJECT_CLASS (fu_redfish_client_parent_class)->finalize (object);
|
||||
}
|
||||
@ -837,6 +806,11 @@ static void
|
||||
fu_redfish_client_init (FuRedfishClient *self)
|
||||
{
|
||||
self->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
self->curl = curl_easy_init ();
|
||||
|
||||
/* since DSP0266 makes Basic Authorization a requirement,
|
||||
* it is safe to use Basic Auth for all implementations */
|
||||
curl_easy_setopt (self->curl, CURLOPT_HTTPAUTH, (glong) CURLAUTH_BASIC);
|
||||
}
|
||||
|
||||
FuRedfishClient *
|
||||
|
@ -21,6 +21,7 @@ shared_module('fu_plugin_redfish',
|
||||
c_args : cargs,
|
||||
dependencies : [
|
||||
plugin_deps,
|
||||
libcurl,
|
||||
libjsonglib,
|
||||
],
|
||||
)
|
||||
@ -45,6 +46,7 @@ if get_option('tests')
|
||||
],
|
||||
dependencies : [
|
||||
plugin_deps,
|
||||
libcurl,
|
||||
libjsonglib,
|
||||
],
|
||||
link_with : [
|
||||
|
@ -35,6 +35,8 @@ apps:
|
||||
command: fwupdagent.wrapper
|
||||
|
||||
parts:
|
||||
curl:
|
||||
source: https://curl.se/download/curl-7.73.0.tar.bz2
|
||||
tpm2-tss:
|
||||
plugin: autotools
|
||||
source: https://github.com/tpm2-software/tpm2-tss/releases/download/2.3.0/tpm2-tss-2.3.0.tar.gz
|
||||
@ -211,7 +213,6 @@ parts:
|
||||
- libpci-dev
|
||||
- libpolkit-gobject-1-dev
|
||||
- libsmbios-dev
|
||||
- libsoup2.4-dev
|
||||
- libsqlite3-dev
|
||||
- libsystemd-dev
|
||||
- locales
|
||||
@ -232,7 +233,6 @@ parts:
|
||||
- libjson-glib-1.0-0
|
||||
- libpolkit-gobject-1-0
|
||||
- libsmbios-c2
|
||||
- libsoup2.4-1
|
||||
- glib-networking
|
||||
- libglib2.0-bin
|
||||
prime:
|
||||
@ -272,7 +272,7 @@ parts:
|
||||
- -usr/lib/*/pkgconfig
|
||||
# we don't want system gnutls leaking in
|
||||
- -usr/lib/*/libgnutls*
|
||||
after: [meson, build-introspection, modemmanager, libmbim, libqmi, tpm2-tss, gnutls]
|
||||
after: [meson, build-introspection, modemmanager, libmbim, libqmi, tpm2-tss, gnutls, curl]
|
||||
fix-bash-completion:
|
||||
plugin: make
|
||||
source: contrib/snap/fix-bash-completion
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <libsoup/soup.h>
|
||||
#include <jcat.h>
|
||||
|
||||
#include "fu-device-private.h"
|
||||
@ -912,13 +911,11 @@ static gchar *
|
||||
fu_util_download_if_required (FuUtilPrivate *priv, const gchar *perhapsfn, GError **error)
|
||||
{
|
||||
g_autofree gchar *filename = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
|
||||
/* a local file */
|
||||
uri = soup_uri_new (perhapsfn);
|
||||
if (g_file_test (perhapsfn, G_FILE_TEST_EXISTS))
|
||||
return g_strdup (perhapsfn);
|
||||
if (uri == NULL)
|
||||
if (!fu_util_is_url (perhapsfn))
|
||||
return g_strdup (perhapsfn);
|
||||
|
||||
/* download the firmware to a cachedir */
|
||||
@ -1079,7 +1076,6 @@ fu_util_install_release (FuUtilPrivate *priv, FwupdRelease *rel, GError **error)
|
||||
const gchar *remote_id;
|
||||
const gchar *uri_tmp;
|
||||
g_auto(GStrv) argv = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
|
||||
uri_tmp = fwupd_release_get_uri (rel);
|
||||
if (uri_tmp == NULL) {
|
||||
@ -1107,8 +1103,8 @@ fu_util_install_release (FuUtilPrivate *priv, FwupdRelease *rel, GError **error)
|
||||
|
||||
argv = g_new0 (gchar *, 2);
|
||||
/* local remotes may have the firmware already */
|
||||
uri = soup_uri_new (uri_tmp);
|
||||
if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL && uri == NULL) {
|
||||
if (fwupd_remote_get_kind (remote) == FWUPD_REMOTE_KIND_LOCAL &&
|
||||
!fu_util_is_url (uri_tmp)) {
|
||||
const gchar *fn_cache = fwupd_remote_get_filename_cache (remote);
|
||||
g_autofree gchar *path = g_path_get_dirname (fn_cache);
|
||||
argv[0] = g_build_filename (path, uri_tmp, NULL);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <gusb.h>
|
||||
#include <xmlb.h>
|
||||
#include <fwupd.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "fu-common.h"
|
||||
#include "fu-device-private.h"
|
||||
@ -2007,3 +2008,12 @@ fu_util_show_unsupported_warn (void)
|
||||
g_printerr ("%s %s\n", fmt, _("This package has not been validated, it may not work properly."));
|
||||
#endif
|
||||
}
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURLU, curl_url_cleanup)
|
||||
|
||||
gboolean
|
||||
fu_util_is_url (const gchar *perhaps_url)
|
||||
{
|
||||
g_autoptr(CURLU) h = curl_url ();
|
||||
return curl_url_set (h, CURLUPART_URL, perhaps_url, 0) == CURLUE_OK;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <fwupd.h>
|
||||
#include <libsoup/soup.h>
|
||||
|
||||
/* this is only valid for tools */
|
||||
#define FWUPD_ERROR_INVALID_ARGS (FWUPD_ERROR_LAST+1)
|
||||
@ -119,3 +118,4 @@ gboolean fu_util_switch_branch_warning (FwupdDevice *dev,
|
||||
gboolean assume_yes,
|
||||
GError **error);
|
||||
void fu_util_show_unsupported_warn (void);
|
||||
gboolean fu_util_is_url (const gchar *perhaps_url);
|
||||
|
@ -584,13 +584,11 @@ fu_util_download_if_required (FuUtilPrivate *priv, const gchar *perhapsfn, GErro
|
||||
{
|
||||
g_autofree gchar *filename = NULL;
|
||||
g_autoptr(GBytes) blob = NULL;
|
||||
g_autoptr(SoupURI) uri = NULL;
|
||||
|
||||
/* a local file */
|
||||
if (g_file_test (perhapsfn, G_FILE_TEST_EXISTS))
|
||||
return g_strdup (perhapsfn);
|
||||
uri = soup_uri_new (perhapsfn);
|
||||
if (uri == NULL)
|
||||
if (!fu_util_is_url (perhapsfn))
|
||||
return g_strdup (perhapsfn);
|
||||
|
||||
/* download the firmware to a cachedir */
|
||||
|
@ -34,11 +34,11 @@ fwupdmgr = executable(
|
||||
fwupdplugin_incdir,
|
||||
],
|
||||
dependencies : [
|
||||
libcurl,
|
||||
libxmlb,
|
||||
giounix,
|
||||
gudev,
|
||||
gusb,
|
||||
soup,
|
||||
sqlite,
|
||||
libarchive,
|
||||
libjsonglib,
|
||||
@ -67,11 +67,11 @@ fwupdagent = executable(
|
||||
fwupdplugin_incdir,
|
||||
],
|
||||
dependencies : [
|
||||
libcurl,
|
||||
libxmlb,
|
||||
giounix,
|
||||
gudev,
|
||||
gusb,
|
||||
soup,
|
||||
libjsonglib,
|
||||
],
|
||||
link_with : [
|
||||
@ -102,9 +102,9 @@ fwupdoffline = executable(
|
||||
giounix,
|
||||
gudev,
|
||||
gusb,
|
||||
libcurl,
|
||||
libjsonglib,
|
||||
libxmlb,
|
||||
soup,
|
||||
sqlite,
|
||||
],
|
||||
link_with : [
|
||||
@ -153,6 +153,7 @@ fwupdtool = executable(
|
||||
fwupdplugin_incdir,
|
||||
],
|
||||
dependencies : [
|
||||
libcurl,
|
||||
libjcat,
|
||||
libxmlb,
|
||||
libgcab,
|
||||
@ -160,7 +161,6 @@ fwupdtool = executable(
|
||||
gmodule,
|
||||
gudev,
|
||||
gusb,
|
||||
soup,
|
||||
sqlite,
|
||||
valgrind,
|
||||
libarchive,
|
||||
@ -263,7 +263,6 @@ executable(
|
||||
gmodule,
|
||||
gudev,
|
||||
gusb,
|
||||
soup,
|
||||
sqlite,
|
||||
valgrind,
|
||||
libarchive,
|
||||
@ -323,7 +322,6 @@ if get_option('tests')
|
||||
gmodule,
|
||||
gudev,
|
||||
gusb,
|
||||
soup,
|
||||
sqlite,
|
||||
valgrind,
|
||||
libarchive,
|
||||
|
Loading…
Reference in New Issue
Block a user