diff options
| author | Sebastien Bacher <seb128@ubuntu.com> | 2021-07-05 20:35:03 +0200 |
|---|---|---|
| committer | Sebastien Bacher <seb128@ubuntu.com> | 2021-07-05 20:35:03 +0200 |
| commit | 35779c6675728fa6f0fd0a21cefb904408509c23 (patch) | |
| tree | 553e7239e0ba182b4f9b29b1e7a9d66a595d08bc /src/nm-cloud-setup/nmcs-provider.c | |
| parent | d92aa7f298fe84d4cf686c5ad64b73438e00d377 (diff) | |
New upstream version 1.32.2
Diffstat (limited to 'src/nm-cloud-setup/nmcs-provider.c')
| -rw-r--r-- | src/nm-cloud-setup/nmcs-provider.c | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/src/nm-cloud-setup/nmcs-provider.c b/src/nm-cloud-setup/nmcs-provider.c new file mode 100644 index 00000000..678152aa --- /dev/null +++ b/src/nm-cloud-setup/nmcs-provider.c @@ -0,0 +1,288 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "libnm-client-aux-extern/nm-default-client.h" + +#include "nmcs-provider.h" + +#include "nm-cloud-setup-utils.h" + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_HTTP_CLIENT, ); + +typedef struct _NMCSProviderPrivate { + NMHttpClient *http_client; +} NMCSProviderPrivate; + +G_DEFINE_TYPE(NMCSProvider, nmcs_provider, G_TYPE_OBJECT); + +#define NMCS_PROVIDER_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMCSProvider, NMCS_IS_PROVIDER) + +/*****************************************************************************/ + +const char * +nmcs_provider_get_name(NMCSProvider *self) +{ + NMCSProviderClass *klass; + + g_return_val_if_fail(NMCS_IS_PROVIDER(self), NULL); + + klass = NMCS_PROVIDER_GET_CLASS(self); + nm_assert(klass->_name); + return klass->_name; +} + +/*****************************************************************************/ + +NMHttpClient * +nmcs_provider_get_http_client(NMCSProvider *self) +{ + g_return_val_if_fail(NMCS_IS_PROVIDER(self), NULL); + + return NMCS_PROVIDER_GET_PRIVATE(self)->http_client; +} + +GMainContext * +nmcs_provider_get_main_context(NMCSProvider *self) +{ + g_return_val_if_fail(NMCS_IS_PROVIDER(self), NULL); + + return nm_http_client_get_main_context(NMCS_PROVIDER_GET_PRIVATE(self)->http_client); +} + +/*****************************************************************************/ + +void +nmcs_provider_detect(NMCSProvider * self, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + gs_unref_object GTask *task = NULL; + const char * env; + + g_return_if_fail(NMCS_IS_PROVIDER(self)); + g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable)); + + task = nm_g_task_new(self, cancellable, nmcs_provider_detect, callback, user_data); + + nmcs_wait_for_objects_register(task); + + env = g_getenv(NMCS_PROVIDER_GET_CLASS(self)->_env_provider_enabled); + if (!_nm_utils_ascii_str_to_bool(env, FALSE)) { + g_task_return_error(task, + nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "provider is disabled")); + return; + } + + NMCS_PROVIDER_GET_CLASS(self)->detect(self, g_steal_pointer(&task)); +} + +gboolean +nmcs_provider_detect_finish(NMCSProvider *self, GAsyncResult *result, GError **error) +{ + g_return_val_if_fail(NMCS_IS_PROVIDER(self), FALSE); + g_return_val_if_fail(nm_g_task_is_valid(result, self, nmcs_provider_detect), FALSE); + + return g_task_propagate_boolean(G_TASK(result), error); +} + +/*****************************************************************************/ + +NMCSProviderGetConfigIfaceData * +nmcs_provider_get_config_iface_data_new(gboolean was_requested) +{ + NMCSProviderGetConfigIfaceData *iface_data; + + iface_data = g_slice_new(NMCSProviderGetConfigIfaceData); + *iface_data = (NMCSProviderGetConfigIfaceData){ + .iface_idx = -1, + .was_requested = was_requested, + }; + return iface_data; +} + +static void +_iface_data_free(gpointer data) +{ + NMCSProviderGetConfigIfaceData *iface_data = data; + + g_free(iface_data->ipv4s_arr); + g_free(iface_data->iproutes_arr); + + nm_g_slice_free(iface_data); +} + +static void +_get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data, GError *error_take) +{ + gs_free_error GError *error = error_take; + + nm_assert(get_config_data); + nm_assert(G_IS_TASK(get_config_data->task)); + + if (!error) { + if (get_config_data->n_pending > 0) + return; + } + + g_cancellable_cancel(get_config_data->intern_cancellable); + + if (error) { + if (nm_utils_error_is_cancelled(error)) + _LOGD("get-config: cancelled"); + else + _LOGD("get-config: failed: %s", error->message); + g_task_return_error(get_config_data->task, g_steal_pointer(&error)); + } else { + _LOGD("get-config: success"); + g_task_return_pointer(get_config_data->task, + g_hash_table_ref(get_config_data->result_dict), + (GDestroyNotify) g_hash_table_unref); + } + + nm_clear_g_signal_handler(g_task_get_cancellable(get_config_data->task), + &get_config_data->extern_cancelled_id); + + if (get_config_data->extra_data_destroy) + get_config_data->extra_data_destroy(get_config_data->extra_data); + + nm_clear_pointer(&get_config_data->result_dict, g_hash_table_unref); + + nm_g_object_unref(get_config_data->intern_cancellable); + g_object_unref(get_config_data->task); + nm_g_slice_free(get_config_data); +} + +void +_nmcs_provider_get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data, + GError * error_take) +{ + nm_assert(!error_take || !nm_utils_error_is_cancelled(error_take)); + _get_config_task_maybe_return(get_config_data, error_take); +} + +static void +_get_config_cancelled_cb(GObject *object, gpointer user_data) +{ + _get_config_task_maybe_return(user_data, nm_utils_error_new_cancelled(FALSE, NULL)); +} + +void +nmcs_provider_get_config(NMCSProvider * self, + gboolean any, + const char *const * hwaddrs, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMCSProviderGetConfigTaskData *get_config_data; + + g_return_if_fail(NMCS_IS_PROVIDER(self)); + g_return_if_fail(!cancellable || G_IS_CANCELLABLE(cancellable)); + + _LOGD("get-config: starting"); + + get_config_data = g_slice_new(NMCSProviderGetConfigTaskData); + *get_config_data = (NMCSProviderGetConfigTaskData){ + .task = nm_g_task_new(self, cancellable, nmcs_provider_get_config, callback, user_data), + .any = any, + .result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _iface_data_free), + }; + + nmcs_wait_for_objects_register(get_config_data->task); + + for (; hwaddrs && hwaddrs[0]; hwaddrs++) { + g_hash_table_insert(get_config_data->result_dict, + g_strdup(hwaddrs[0]), + nmcs_provider_get_config_iface_data_new(TRUE)); + } + + if (cancellable) { + gulong cancelled_id; + + cancelled_id = g_cancellable_connect(cancellable, + G_CALLBACK(_get_config_cancelled_cb), + get_config_data, + NULL); + if (cancelled_id == 0) { + /* the callback was already invoked synchronously and the task already returned. */ + return; + } + + get_config_data->extern_cancelled_id = cancelled_id; + get_config_data->intern_cancellable = g_cancellable_new(); + } + + NMCS_PROVIDER_GET_CLASS(self)->get_config(self, get_config_data); +} + +GHashTable * +nmcs_provider_get_config_finish(NMCSProvider *self, GAsyncResult *result, GError **error) +{ + g_return_val_if_fail(NMCS_IS_PROVIDER(self), FALSE); + g_return_val_if_fail(nm_g_task_is_valid(result, self, nmcs_provider_get_config), FALSE); + + return g_task_propagate_pointer(G_TASK(result), error); +} + +/*****************************************************************************/ + +static void +set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + NMCSProviderPrivate *priv = NMCS_PROVIDER_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_HTTP_CLIENT: + priv->http_client = g_value_dup_object(value); + g_return_if_fail(NM_IS_HTTP_CLIENT(priv->http_client)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nmcs_provider_init(NMCSProvider *self) +{ + NMCSProviderPrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NMCS_TYPE_PROVIDER, NMCSProviderPrivate); + + self->_priv = priv; +} + +static void +dispose(GObject *object) +{ + NMCSProvider * self = NMCS_PROVIDER(object); + NMCSProviderPrivate *priv = NMCS_PROVIDER_GET_PRIVATE(self); + + g_clear_object(&priv->http_client); + + G_OBJECT_CLASS(nmcs_provider_parent_class)->dispose(object); +} + +static void +nmcs_provider_class_init(NMCSProviderClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(object_class, sizeof(NMCSProviderPrivate)); + + object_class->set_property = set_property; + object_class->dispose = dispose; + + obj_properties[PROP_HTTP_CLIENT] = + g_param_spec_object(NMCS_PROVIDER_HTTP_CLIENT, + "", + "", + NM_TYPE_HTTP_CLIENT, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} |