diff options
| author | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
| commit | aafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch) | |
| tree | a2a9bb4d007339a0b1304540388230ccedac32bd /clients/cloud-setup/nm-cloud-setup-utils.c | |
| parent | e7b44ef4c80907346ec7492a09c45277459924fc (diff) | |
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'clients/cloud-setup/nm-cloud-setup-utils.c')
| -rw-r--r-- | clients/cloud-setup/nm-cloud-setup-utils.c | 1179 |
1 files changed, 586 insertions, 593 deletions
diff --git a/clients/cloud-setup/nm-cloud-setup-utils.c b/clients/cloud-setup/nm-cloud-setup-utils.c index ff059e7a..0820ed59 100644 --- a/clients/cloud-setup/nm-cloud-setup-utils.c +++ b/clients/cloud-setup/nm-cloud-setup-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ #include "nm-default.h" @@ -6,91 +6,96 @@ #include "nm-glib-aux/nm-time-utils.h" #include "nm-glib-aux/nm-logging-base.h" +#include "nm-glib-aux/nm-str-buf.h" /*****************************************************************************/ volatile NMLogLevel _nm_logging_configured_level = LOGL_TRACE; void -_nm_logging_enabled_init (const char *level_str) +_nm_logging_enabled_init(const char *level_str) { - NMLogLevel level; + NMLogLevel level; - if (!_nm_log_parse_level (level_str, &level)) - level = LOGL_WARN; - else if (level == _LOGL_KEEP) - level = LOGL_WARN; + if (!_nm_log_parse_level(level_str, &level)) + level = LOGL_WARN; + else if (level == _LOGL_KEEP) + level = LOGL_WARN; - _nm_logging_configured_level = level; + _nm_logging_configured_level = level; } void -_nm_log_impl_cs (NMLogLevel level, - const char *fmt, - ...) +_nm_log_impl_cs(NMLogLevel level, const char *fmt, ...) { - gs_free char *msg = NULL; - va_list ap; - const char *level_str; - gint64 ts; - - va_start (ap, fmt); - msg = g_strdup_vprintf (fmt, ap); - va_end (ap); - - switch (level) { - case LOGL_TRACE: level_str = "<trace>"; break; - case LOGL_DEBUG: level_str = "<debug>"; break; - case LOGL_INFO: level_str = "<info> "; break; - case LOGL_WARN: level_str = "<warn> "; break; - default: - nm_assert (level == LOGL_ERR); - level_str = "<error>"; - break; - } - - ts = nm_utils_clock_gettime_nsec (CLOCK_BOOTTIME); - - g_print ("[%"G_GINT64_FORMAT".%05"G_GINT64_FORMAT"] %s %s\n", - ts / NM_UTILS_NSEC_PER_SEC, - (ts / (NM_UTILS_NSEC_PER_SEC / 10000)) % 10000, - level_str, - msg); + gs_free char *msg = NULL; + va_list ap; + const char * level_str; + gint64 ts; + + va_start(ap, fmt); + msg = g_strdup_vprintf(fmt, ap); + va_end(ap); + + switch (level) { + case LOGL_TRACE: + level_str = "<trace>"; + break; + case LOGL_DEBUG: + level_str = "<debug>"; + break; + case LOGL_INFO: + level_str = "<info> "; + break; + case LOGL_WARN: + level_str = "<warn> "; + break; + default: + nm_assert(level == LOGL_ERR); + level_str = "<error>"; + break; + } + + ts = nm_utils_clock_gettime_nsec(CLOCK_BOOTTIME); + + g_print("[%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] %s %s\n", + ts / NM_UTILS_NSEC_PER_SEC, + (ts / (NM_UTILS_NSEC_PER_SEC / 10000)) % 10000, + level_str, + msg); } void -_nm_utils_monotonic_timestamp_initialized (const struct timespec *tp, - gint64 offset_sec, - gboolean is_boottime) -{ -} +_nm_utils_monotonic_timestamp_initialized(const struct timespec *tp, + gint64 offset_sec, + gboolean is_boottime) +{} /*****************************************************************************/ -G_LOCK_DEFINE_STATIC (_wait_for_objects_lock); +G_LOCK_DEFINE_STATIC(_wait_for_objects_lock); static GSList *_wait_for_objects_list; static GSList *_wait_for_objects_iterate_loops; static void -_wait_for_objects_maybe_quit_mainloops_with_lock (void) +_wait_for_objects_maybe_quit_mainloops_with_lock(void) { - GSList *iter; + GSList *iter; - if (!_wait_for_objects_list) { - for (iter = _wait_for_objects_iterate_loops; iter; iter = iter->next) - g_main_loop_quit (iter->data); - } + if (!_wait_for_objects_list) { + for (iter = _wait_for_objects_iterate_loops; iter; iter = iter->next) + g_main_loop_quit(iter->data); + } } static void -_wait_for_objects_weak_cb (gpointer data, - GObject *where_the_object_was) +_wait_for_objects_weak_cb(gpointer data, GObject *where_the_object_was) { - G_LOCK (_wait_for_objects_lock); - nm_assert (g_slist_find (_wait_for_objects_list, where_the_object_was)); - _wait_for_objects_list = g_slist_remove (_wait_for_objects_list, where_the_object_was); - _wait_for_objects_maybe_quit_mainloops_with_lock (); - G_UNLOCK (_wait_for_objects_lock); + G_LOCK(_wait_for_objects_lock); + nm_assert(g_slist_find(_wait_for_objects_list, where_the_object_was)); + _wait_for_objects_list = g_slist_remove(_wait_for_objects_list, where_the_object_was); + _wait_for_objects_maybe_quit_mainloops_with_lock(); + G_UNLOCK(_wait_for_objects_lock); } /** @@ -102,55 +107,53 @@ _wait_for_objects_weak_cb (gpointer data, * @target gets destroyed, which means that it gets completely unreferenced. */ gpointer -nmcs_wait_for_objects_register (gpointer target) +nmcs_wait_for_objects_register(gpointer target) { - g_return_val_if_fail (G_IS_OBJECT (target), NULL); + g_return_val_if_fail(G_IS_OBJECT(target), NULL); - G_LOCK (_wait_for_objects_lock); - _wait_for_objects_list = g_slist_prepend (_wait_for_objects_list, target); - G_UNLOCK (_wait_for_objects_lock); + G_LOCK(_wait_for_objects_lock); + _wait_for_objects_list = g_slist_prepend(_wait_for_objects_list, target); + G_UNLOCK(_wait_for_objects_lock); - g_object_weak_ref (target, - _wait_for_objects_weak_cb, - NULL); - return target; + g_object_weak_ref(target, _wait_for_objects_weak_cb, NULL); + return target; } typedef struct { - GMainLoop *loop; - gboolean got_timeout; + GMainLoop *loop; + gboolean got_timeout; } WaitForObjectsData; static gboolean -_wait_for_objects_iterate_until_done_timeout_cb (gpointer user_data) +_wait_for_objects_iterate_until_done_timeout_cb(gpointer user_data) { - WaitForObjectsData *data = user_data; + WaitForObjectsData *data = user_data; - data->got_timeout = TRUE; - g_main_loop_quit (data->loop); - return G_SOURCE_CONTINUE; + data->got_timeout = TRUE; + g_main_loop_quit(data->loop); + return G_SOURCE_CONTINUE; } static gboolean -_wait_for_objects_iterate_until_done_idle_cb (gpointer user_data) +_wait_for_objects_iterate_until_done_idle_cb(gpointer user_data) { - /* This avoids a race where: - * - * - we check whether there are objects to wait for. - * - the last object to wait for gets removed (issuing g_main_loop_quit()). - * - we run the mainloop (and missed our signal). - * - * It's really a missing feature of GMainLoop where the "is-running" flag is always set to - * TRUE by g_main_loop_run(). That means, you cannot catch a g_main_loop_quit() in a race - * free way while not iterating the loop. - * - * Avoid this, by checking once again after we start running the mainloop. - */ - - G_LOCK (_wait_for_objects_lock); - _wait_for_objects_maybe_quit_mainloops_with_lock (); - G_UNLOCK (_wait_for_objects_lock); - return G_SOURCE_REMOVE; + /* This avoids a race where: + * + * - we check whether there are objects to wait for. + * - the last object to wait for gets removed (issuing g_main_loop_quit()). + * - we run the mainloop (and missed our signal). + * + * It's really a missing feature of GMainLoop where the "is-running" flag is always set to + * TRUE by g_main_loop_run(). That means, you cannot catch a g_main_loop_quit() in a race + * free way while not iterating the loop. + * + * Avoid this, by checking once again after we start running the mainloop. + */ + + G_LOCK(_wait_for_objects_lock); + _wait_for_objects_maybe_quit_mainloops_with_lock(); + G_UNLOCK(_wait_for_objects_lock); + return G_SOURCE_REMOVE; } /** @@ -168,211 +171,204 @@ _wait_for_objects_iterate_until_done_idle_cb (gpointer user_data) * Returns: %FALSE on timeout or %TRUE if all objects destroyed before timeout. */ gboolean -nmcs_wait_for_objects_iterate_until_done (GMainContext *context, - int timeout_msec) +nmcs_wait_for_objects_iterate_until_done(GMainContext *context, int timeout_msec) { - nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new (context, FALSE); - nm_auto_destroy_and_unref_gsource GSource *timeout_source = NULL; - WaitForObjectsData data; - gboolean has_more_objects; - - G_LOCK (_wait_for_objects_lock); - if (!_wait_for_objects_list) { - G_UNLOCK (_wait_for_objects_lock); - return TRUE; - } - _wait_for_objects_iterate_loops = g_slist_prepend (_wait_for_objects_iterate_loops, loop); - G_UNLOCK (_wait_for_objects_lock); - - data = (WaitForObjectsData) { - .loop = loop, - .got_timeout = FALSE, - }; - - if (timeout_msec >= 0) { - timeout_source = nm_g_source_attach (nm_g_timeout_source_new (timeout_msec, - G_PRIORITY_DEFAULT, - _wait_for_objects_iterate_until_done_timeout_cb, - &data, - NULL), - context); - } - - has_more_objects = TRUE; - while ( has_more_objects - && !data.got_timeout) { - nm_auto_destroy_and_unref_gsource GSource *idle_source = NULL; - - idle_source = nm_g_source_attach (nm_g_idle_source_new (G_PRIORITY_DEFAULT, - _wait_for_objects_iterate_until_done_idle_cb, - &data, - NULL), - context); - - g_main_loop_run (loop); - - G_LOCK (_wait_for_objects_lock); - has_more_objects = (!!_wait_for_objects_list); - if ( data.got_timeout - || !has_more_objects) - _wait_for_objects_iterate_loops = g_slist_remove (_wait_for_objects_iterate_loops, loop); - G_UNLOCK (_wait_for_objects_lock); - } - - return !data.got_timeout; + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(context, FALSE); + nm_auto_destroy_and_unref_gsource GSource *timeout_source = NULL; + WaitForObjectsData data; + gboolean has_more_objects; + + G_LOCK(_wait_for_objects_lock); + if (!_wait_for_objects_list) { + G_UNLOCK(_wait_for_objects_lock); + return TRUE; + } + _wait_for_objects_iterate_loops = g_slist_prepend(_wait_for_objects_iterate_loops, loop); + G_UNLOCK(_wait_for_objects_lock); + + data = (WaitForObjectsData){ + .loop = loop, + .got_timeout = FALSE, + }; + + if (timeout_msec >= 0) { + timeout_source = nm_g_source_attach( + nm_g_timeout_source_new(timeout_msec, + G_PRIORITY_DEFAULT, + _wait_for_objects_iterate_until_done_timeout_cb, + &data, + NULL), + context); + } + + has_more_objects = TRUE; + while (has_more_objects && !data.got_timeout) { + nm_auto_destroy_and_unref_gsource GSource *idle_source = NULL; + + idle_source = + nm_g_source_attach(nm_g_idle_source_new(G_PRIORITY_DEFAULT, + _wait_for_objects_iterate_until_done_idle_cb, + &data, + NULL), + context); + + g_main_loop_run(loop); + + G_LOCK(_wait_for_objects_lock); + has_more_objects = (!!_wait_for_objects_list); + if (data.got_timeout || !has_more_objects) + _wait_for_objects_iterate_loops = g_slist_remove(_wait_for_objects_iterate_loops, loop); + G_UNLOCK(_wait_for_objects_lock); + } + + return !data.got_timeout; } /*****************************************************************************/ typedef struct { - GTask *task; - GSource *source_timeout; - GSource *source_next_poll; - GMainContext *context; - GCancellable *internal_cancellable; - NMCSUtilsPollProbeStartFcn probe_start_fcn; - NMCSUtilsPollProbeFinishFcn probe_finish_fcn; - gpointer probe_user_data; - gulong cancellable_id; - gint64 last_poll_start_ms; - int sleep_timeout_ms; - int ratelimit_timeout_ms; - bool completed:1; + GTask * task; + GSource * source_timeout; + GSource * source_next_poll; + GMainContext * context; + GCancellable * internal_cancellable; + NMCSUtilsPollProbeStartFcn probe_start_fcn; + NMCSUtilsPollProbeFinishFcn probe_finish_fcn; + gpointer probe_user_data; + gulong cancellable_id; + gint64 last_poll_start_ms; + int sleep_timeout_ms; + int ratelimit_timeout_ms; + bool completed : 1; } PollTaskData; static void -_poll_task_data_free (gpointer data) +_poll_task_data_free(gpointer data) { - PollTaskData *poll_task_data = data; + PollTaskData *poll_task_data = data; - nm_assert (G_IS_TASK (poll_task_data->task)); - nm_assert (!poll_task_data->source_next_poll); - nm_assert (!poll_task_data->source_timeout); - nm_assert (poll_task_data->cancellable_id == 0); + nm_assert(G_IS_TASK(poll_task_data->task)); + nm_assert(!poll_task_data->source_next_poll); + nm_assert(!poll_task_data->source_timeout); + nm_assert(poll_task_data->cancellable_id == 0); - g_main_context_unref (poll_task_data->context); + g_main_context_unref(poll_task_data->context); - nm_g_slice_free (poll_task_data); + nm_g_slice_free(poll_task_data); } static void -_poll_return (PollTaskData *poll_task_data, - gboolean success, - GError *error_take) +_poll_return(PollTaskData *poll_task_data, GError *error_take) { - nm_clear_g_source_inst (&poll_task_data->source_next_poll); - nm_clear_g_source_inst (&poll_task_data->source_timeout); - nm_clear_g_cancellable_disconnect (g_task_get_cancellable (poll_task_data->task), - &poll_task_data->cancellable_id); + nm_clear_g_source_inst(&poll_task_data->source_next_poll); + nm_clear_g_source_inst(&poll_task_data->source_timeout); + nm_clear_g_cancellable_disconnect(g_task_get_cancellable(poll_task_data->task), + &poll_task_data->cancellable_id); - nm_clear_g_cancellable (&poll_task_data->internal_cancellable); + nm_clear_g_cancellable(&poll_task_data->internal_cancellable); - if (error_take) - g_task_return_error (poll_task_data->task, g_steal_pointer (&error_take)); - else - g_task_return_boolean (poll_task_data->task, success); + if (error_take) + g_task_return_error(poll_task_data->task, g_steal_pointer(&error_take)); + else + g_task_return_boolean(poll_task_data->task, TRUE); - g_object_unref (poll_task_data->task); + g_object_unref(poll_task_data->task); } -static gboolean _poll_start_cb (gpointer user_data); +static gboolean _poll_start_cb(gpointer user_data); static void -_poll_done_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) +_poll_done_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - PollTaskData *poll_task_data = user_data; - _nm_unused gs_unref_object GTask *task = poll_task_data->task; /* balance ref from _poll_start_cb() */ - gs_free_error GError *error = NULL; - gint64 now_ms; - gint64 wait_ms; - gboolean is_finished; - - is_finished = poll_task_data->probe_finish_fcn (source, - result, - poll_task_data->probe_user_data, - &error); - - if (nm_utils_error_is_cancelled (error)) { - /* we already handle this differently. Nothing to do. */ - return; - } - - if ( error - || is_finished) { - _poll_return (poll_task_data, TRUE, g_steal_pointer (&error)); - return; - } - - now_ms = nm_utils_get_monotonic_timestamp_msec (); - if (poll_task_data->ratelimit_timeout_ms > 0) - wait_ms = (poll_task_data->last_poll_start_ms + poll_task_data->ratelimit_timeout_ms) - now_ms; - else - wait_ms = 0; - if (poll_task_data->sleep_timeout_ms > 0) - wait_ms = MAX (wait_ms, poll_task_data->sleep_timeout_ms); - - poll_task_data->source_next_poll = nm_g_source_attach (nm_g_timeout_source_new (MAX (1, wait_ms), - G_PRIORITY_DEFAULT, - _poll_start_cb, - poll_task_data, - NULL), - poll_task_data->context); + PollTaskData * poll_task_data = user_data; + _nm_unused gs_unref_object GTask *task = + poll_task_data->task; /* balance ref from _poll_start_cb() */ + gs_free_error GError *error = NULL; + gint64 now_ms; + gint64 wait_ms; + gboolean is_finished; + + is_finished = + poll_task_data->probe_finish_fcn(source, result, poll_task_data->probe_user_data, &error); + + if (nm_utils_error_is_cancelled(error)) { + /* we already handle this differently. Nothing to do. */ + return; + } + + if (error || is_finished) { + _poll_return(poll_task_data, g_steal_pointer(&error)); + return; + } + + now_ms = nm_utils_get_monotonic_timestamp_msec(); + if (poll_task_data->ratelimit_timeout_ms > 0) + wait_ms = + (poll_task_data->last_poll_start_ms + poll_task_data->ratelimit_timeout_ms) - now_ms; + else + wait_ms = 0; + if (poll_task_data->sleep_timeout_ms > 0) + wait_ms = MAX(wait_ms, poll_task_data->sleep_timeout_ms); + + poll_task_data->source_next_poll = + nm_g_source_attach(nm_g_timeout_source_new(MAX(1, wait_ms), + G_PRIORITY_DEFAULT, + _poll_start_cb, + poll_task_data, + NULL), + poll_task_data->context); } static gboolean -_poll_start_cb (gpointer user_data) +_poll_start_cb(gpointer user_data) { - PollTaskData *poll_task_data = user_data; + PollTaskData *poll_task_data = user_data; - nm_clear_g_source_inst (&poll_task_data->source_next_poll); + nm_clear_g_source_inst(&poll_task_data->source_next_poll); - poll_task_data->last_poll_start_ms = nm_utils_get_monotonic_timestamp_msec (); + poll_task_data->last_poll_start_ms = nm_utils_get_monotonic_timestamp_msec(); - g_object_ref (poll_task_data->task); /* balanced by _poll_done_cb() */ + g_object_ref(poll_task_data->task); /* balanced by _poll_done_cb() */ - poll_task_data->probe_start_fcn (poll_task_data->internal_cancellable, - poll_task_data->probe_user_data, - _poll_done_cb, - poll_task_data); + poll_task_data->probe_start_fcn(poll_task_data->internal_cancellable, + poll_task_data->probe_user_data, + _poll_done_cb, + poll_task_data); - return G_SOURCE_CONTINUE; + return G_SOURCE_CONTINUE; } static gboolean -_poll_timeout_cb (gpointer user_data) +_poll_timeout_cb(gpointer user_data) { - PollTaskData *poll_task_data = user_data; + PollTaskData *poll_task_data = user_data; - _poll_return (poll_task_data, FALSE, nm_utils_error_new (NM_UTILS_ERROR_UNKNOWN, - "timeout expired")); - return G_SOURCE_CONTINUE; + _poll_return(poll_task_data, nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "timeout expired")); + return G_SOURCE_CONTINUE; } static void -_poll_cancelled_cb (GObject *object, gpointer user_data) +_poll_cancelled_cb(GObject *object, gpointer user_data) { - PollTaskData *poll_task_data = user_data; - GError *error = NULL; - - _LOGD (">> poll cancelled"); - nm_clear_g_signal_handler (g_task_get_cancellable (poll_task_data->task), - &poll_task_data->cancellable_id); - nm_utils_error_set_cancelled (&error, FALSE, NULL); - _poll_return (poll_task_data, FALSE, error); + PollTaskData *poll_task_data = user_data; + GError * error = NULL; + + nm_clear_g_signal_handler(g_task_get_cancellable(poll_task_data->task), + &poll_task_data->cancellable_id); + nm_utils_error_set_cancelled(&error, FALSE, NULL); + _poll_return(poll_task_data, error); } /** * nmcs_utils_poll: * @poll_timeout_ms: if >= 0, then this is the overall timeout for how long we poll. - * When this timeout expires, the request completes with failure (but no error set). + * When this timeout expires, the request completes with failure (and error set). * @ratelimit_timeout_ms: if > 0, we ratelimit the starts from one prope_start_fcn * call to the next. * @sleep_timeout_ms: if > 0, then we wait after a probe finished this timeout * before the next. Together with @ratelimit_timeout_ms this determines how * frequently we probe. - * @probe_start_fcn: used to start a (asynchrnous) probe. A probe must be completed + * @probe_start_fcn: used to start a (asynchronous) probe. A probe must be completed * by calling the provided callback. While a probe is in progress, we will not * start another. This function is already invoked the first time synchronously, * during nmcs_utils_poll(). @@ -388,63 +384,62 @@ _poll_cancelled_cb (GObject *object, gpointer user_data) * actions. */ void -nmcs_utils_poll (int poll_timeout_ms, - int ratelimit_timeout_ms, - int sleep_timeout_ms, - NMCSUtilsPollProbeStartFcn probe_start_fcn, - NMCSUtilsPollProbeFinishFcn probe_finish_fcn, - gpointer probe_user_data, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +nmcs_utils_poll(int poll_timeout_ms, + int ratelimit_timeout_ms, + int sleep_timeout_ms, + NMCSUtilsPollProbeStartFcn probe_start_fcn, + NMCSUtilsPollProbeFinishFcn probe_finish_fcn, + gpointer probe_user_data, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { - PollTaskData *poll_task_data; - - poll_task_data = g_slice_new (PollTaskData); - *poll_task_data = (PollTaskData) { - .task = nm_g_task_new (NULL, cancellable, nmcs_utils_poll, callback, user_data), - .probe_start_fcn = probe_start_fcn, - .probe_finish_fcn = probe_finish_fcn, - .probe_user_data = probe_user_data, - .completed = FALSE, - .context = g_main_context_ref_thread_default (), - .sleep_timeout_ms = sleep_timeout_ms, - .ratelimit_timeout_ms = ratelimit_timeout_ms, - .internal_cancellable = g_cancellable_new (), - }; - - nmcs_wait_for_objects_register (poll_task_data->task); - - g_task_set_task_data (poll_task_data->task, poll_task_data, _poll_task_data_free); - - if (poll_timeout_ms >= 0) { - poll_task_data->source_timeout = nm_g_source_attach (nm_g_timeout_source_new (poll_timeout_ms, - G_PRIORITY_DEFAULT, - _poll_timeout_cb, - poll_task_data, - NULL), - poll_task_data->context); - } - - poll_task_data->source_next_poll = nm_g_source_attach (nm_g_idle_source_new (G_PRIORITY_DEFAULT, - _poll_start_cb, - poll_task_data, - NULL), - poll_task_data->context); - - if (cancellable) { - gulong signal_id; - - signal_id = g_cancellable_connect (cancellable, - G_CALLBACK (_poll_cancelled_cb), - poll_task_data, - NULL); - if (signal_id == 0) { - /* the request is already cancelled. Return. */ - return; - } - poll_task_data->cancellable_id = signal_id; - } + PollTaskData *poll_task_data; + + poll_task_data = g_slice_new(PollTaskData); + *poll_task_data = (PollTaskData){ + .task = nm_g_task_new(NULL, cancellable, nmcs_utils_poll, callback, user_data), + .probe_start_fcn = probe_start_fcn, + .probe_finish_fcn = probe_finish_fcn, + .probe_user_data = probe_user_data, + .completed = FALSE, + .context = g_main_context_ref_thread_default(), + .sleep_timeout_ms = sleep_timeout_ms, + .ratelimit_timeout_ms = ratelimit_timeout_ms, + .internal_cancellable = g_cancellable_new(), + }; + + nmcs_wait_for_objects_register(poll_task_data->task); + + g_task_set_task_data(poll_task_data->task, poll_task_data, _poll_task_data_free); + + if (poll_timeout_ms >= 0) { + poll_task_data->source_timeout = + nm_g_source_attach(nm_g_timeout_source_new(poll_timeout_ms, + G_PRIORITY_DEFAULT, + _poll_timeout_cb, + poll_task_data, + NULL), + poll_task_data->context); + } + + poll_task_data->source_next_poll = nm_g_source_attach( + nm_g_idle_source_new(G_PRIORITY_DEFAULT, _poll_start_cb, poll_task_data, NULL), + poll_task_data->context); + + if (cancellable) { + gulong signal_id; + + signal_id = g_cancellable_connect(cancellable, + G_CALLBACK(_poll_cancelled_cb), + poll_task_data, + NULL); + if (signal_id == 0) { + /* the request is already cancelled. Return. */ + return; + } + poll_task_data->cancellable_id = signal_id; + } } /** @@ -459,378 +454,376 @@ nmcs_utils_poll (int poll_timeout_ms, * %FALSE will be returned. * If the probe returned a failure, this returns %FALSE and the error * provided by @probe_finish_fcn. - * If the request times out, this returns %FALSE without error set. + * If the request times out, this returns %FALSE with error set. + * Error is always set if (and only if) the function returns %FALSE. */ gboolean -nmcs_utils_poll_finish (GAsyncResult *result, - gpointer *probe_user_data, - GError **error) +nmcs_utils_poll_finish(GAsyncResult *result, gpointer *probe_user_data, GError **error) { - GTask *task; - PollTaskData *poll_task_data; + GTask * task; + PollTaskData *poll_task_data; - g_return_val_if_fail (nm_g_task_is_valid (result, NULL, nmcs_utils_poll), FALSE); - g_return_val_if_fail (!error || !*error, FALSE); + g_return_val_if_fail(nm_g_task_is_valid(result, NULL, nmcs_utils_poll), FALSE); + g_return_val_if_fail(!error || !*error, FALSE); - task = G_TASK (result); + task = G_TASK(result); - if (probe_user_data) { - poll_task_data = g_task_get_task_data (task); - NM_SET_OUT (probe_user_data, poll_task_data->probe_user_data); - } + if (probe_user_data) { + poll_task_data = g_task_get_task_data(task); + NM_SET_OUT(probe_user_data, poll_task_data->probe_user_data); + } - return g_task_propagate_boolean (task, error); + return g_task_propagate_boolean(task, error); } /*****************************************************************************/ char * -nmcs_utils_hwaddr_normalize (const char *hwaddr, gssize len) +nmcs_utils_hwaddr_normalize(const char *hwaddr, gssize len) { - gs_free char *hwaddr_clone = NULL; - guint8 buf[ETH_ALEN]; - - nm_assert (len >= -1); - - if (len < 0) { - if (!hwaddr) - return NULL; - } else { - if (len == 0) - return NULL; - nm_assert (hwaddr); - hwaddr = nm_strndup_a (300, hwaddr, len, &hwaddr_clone); - } - - if (!nm_utils_hwaddr_aton (hwaddr, buf, sizeof (buf))) - return NULL; - - return nm_utils_hwaddr_ntoa (buf, sizeof (buf)); + gs_free char *hwaddr_clone = NULL; + guint8 buf[ETH_ALEN]; + + nm_assert(len >= -1); + + if (len < 0) { + if (!hwaddr) + return NULL; + } else { + if (len == 0) + return NULL; + nm_assert(hwaddr); + hwaddr = nm_strndup_a(300, hwaddr, len, &hwaddr_clone); + } + /* we cannot use _nm_utils_hwaddr_aton() because that requires a delimiter. + * Azure exposes MAC addresses without delimiter, so accept that too. */ + if (!nm_utils_hexstr2bin_full(hwaddr, + FALSE, + FALSE, + FALSE, + ":-", + sizeof(buf), + buf, + sizeof(buf), + NULL)) + return NULL; + + return nm_utils_hwaddr_ntoa(buf, sizeof(buf)); } /*****************************************************************************/ const char * -nmcs_utils_parse_memmem (GBytes *mem, const char *needle) +nmcs_utils_parse_memmem(GBytes *mem, const char *needle) { - const char *mem_data; - gsize mem_size; + const char *mem_data; + gsize mem_size; - g_return_val_if_fail (mem, NULL); - g_return_val_if_fail (needle, NULL); + g_return_val_if_fail(mem, NULL); + g_return_val_if_fail(needle, NULL); - mem_data = g_bytes_get_data (mem, &mem_size); - return memmem (mem_data, mem_size, needle, strlen (needle)); + mem_data = g_bytes_get_data(mem, &mem_size); + return memmem(mem_data, mem_size, needle, strlen(needle)); } const char * -nmcs_utils_parse_get_full_line (GBytes *mem, const char *needle) +nmcs_utils_parse_get_full_line(GBytes *mem, const char *needle) { - const char *mem_data; - gsize mem_size; - gsize c; - gsize l; + const char *mem_data; + gsize mem_size; + gsize c; + gsize l; - const char *line; + const char *line; - line = nmcs_utils_parse_memmem (mem, needle); - if (!line) - return NULL; + line = nmcs_utils_parse_memmem(mem, needle); + if (!line) + return NULL; - mem_data = g_bytes_get_data (mem, &mem_size); + mem_data = g_bytes_get_data(mem, &mem_size); - if ( line != mem_data - && line[-1] != '\n') { - /* the line must be preceeded either by the begin of the data or - * by a newline. */ - return NULL; - } + if (line != mem_data && line[-1] != '\n') { + /* the line must be preceeded either by the begin of the data or + * by a newline. */ + return NULL; + } - c = mem_size - (line - mem_data); - l = strlen (needle); + c = mem_size - (line - mem_data); + l = strlen(needle); - if ( c != l - && line[l] != '\n') { - /* the end of the needle must be either a newline or the end of the buffer. */ - return NULL; - } + if (c != l && line[l] != '\n') { + /* the end of the needle must be either a newline or the end of the buffer. */ + return NULL; + } - return line; + return line; } /*****************************************************************************/ char * -nmcs_utils_uri_build_concat_v (const char *base, - const char **components, - gsize n_components) +nmcs_utils_uri_build_concat_v(const char *base, const char **components, gsize n_components) { - GString *uri; - - nm_assert (base); - nm_assert (base[0]); - nm_assert (!NM_STR_HAS_SUFFIX (base, "/")); - - uri = g_string_sized_new (100); - - g_string_append (uri, base); - - if ( n_components > 0 - && components[0] - && components[0][0] == '/') { - /* the first component starts with a slash. We allow that, and don't add a duplicate - * slash. Otherwise, we add a separator after base. - * - * We only do that for the first component. */ - } else - g_string_append_c (uri, '/'); - - while (n_components > 0) { - if (!components[0]) { - /* we allow NULL, to indicate nothing to append*/ - } else - g_string_append (uri, components[0]); - components++; - n_components--; - } - - return g_string_free (uri, FALSE); + NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); + + nm_assert(base); + nm_assert(base[0]); + nm_assert(!NM_STR_HAS_SUFFIX(base, "/")); + + nm_str_buf_append(&strbuf, base); + + if (n_components > 0 && components[0] && components[0][0] == '/') { + /* the first component starts with a slash. We allow that, and don't add a duplicate + * slash. Otherwise, we add a separator after base. + * + * We only do that for the first component. */ + } else + nm_str_buf_append_c(&strbuf, '/'); + + while (n_components > 0) { + if (!components[0]) { + /* we allow NULL, to indicate nothing to append */ + } else + nm_str_buf_append(&strbuf, components[0]); + components++; + n_components--; + } + + return nm_str_buf_finalize(&strbuf, NULL); } /*****************************************************************************/ gboolean -nmcs_setting_ip_replace_ipv4_addresses (NMSettingIPConfig *s_ip, - NMIPAddress **entries_arr, - guint entries_len) +nmcs_setting_ip_replace_ipv4_addresses(NMSettingIPConfig *s_ip, + NMIPAddress ** entries_arr, + guint entries_len) { - gboolean any_changes = FALSE; - guint i_next; - guint num; - guint i; - - num = nm_setting_ip_config_get_num_addresses (s_ip); - - i_next = 0; - - for (i = 0; i < entries_len; i++) { - NMIPAddress *entry = entries_arr[i]; - - if (!any_changes) { - if (i_next < num) { - if (nm_ip_address_cmp_full (entry, - nm_setting_ip_config_get_address (s_ip, i_next), - NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS) == 0) { - i_next++; - continue; - } - } - while (i_next < num) - nm_setting_ip_config_remove_address (s_ip, --num); - any_changes = TRUE; - } - - if (!nm_setting_ip_config_add_address (s_ip, entry)) - continue; - - i_next++; - } - if (any_changes) { - while (i_next < num) { - nm_setting_ip_config_remove_address (s_ip, --num); - any_changes = TRUE; - } - } - - return any_changes; + gboolean any_changes = FALSE; + guint i_next; + guint num; + guint i; + + num = nm_setting_ip_config_get_num_addresses(s_ip); + + i_next = 0; + + for (i = 0; i < entries_len; i++) { + NMIPAddress *entry = entries_arr[i]; + + if (!any_changes) { + if (i_next < num) { + if (nm_ip_address_cmp_full(entry, + nm_setting_ip_config_get_address(s_ip, i_next), + NM_IP_ADDRESS_CMP_FLAGS_WITH_ATTRS) + == 0) { + i_next++; + continue; + } + } + while (i_next < num) + nm_setting_ip_config_remove_address(s_ip, --num); + any_changes = TRUE; + } + + if (!nm_setting_ip_config_add_address(s_ip, entry)) + continue; + + i_next++; + } + if (any_changes) { + while (i_next < num) { + nm_setting_ip_config_remove_address(s_ip, --num); + any_changes = TRUE; + } + } + + return any_changes; } gboolean -nmcs_setting_ip_replace_ipv4_routes (NMSettingIPConfig *s_ip, - NMIPRoute **entries_arr, - guint entries_len) +nmcs_setting_ip_replace_ipv4_routes(NMSettingIPConfig *s_ip, + NMIPRoute ** entries_arr, + guint entries_len) { - gboolean any_changes = FALSE; - guint i_next; - guint num; - guint i; - - num = nm_setting_ip_config_get_num_routes (s_ip); - - i_next = 0; - - for (i = 0; i < entries_len; i++) { - NMIPRoute *entry = entries_arr[i]; - - if (!any_changes) { - if (i_next < num) { - if (nm_ip_route_equal_full (entry, - nm_setting_ip_config_get_route (s_ip, i_next), - NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) { - i_next++; - continue; - } - } - while (i_next < num) - nm_setting_ip_config_remove_route (s_ip, --num); - any_changes = TRUE; - } - - if (!nm_setting_ip_config_add_route (s_ip, entry)) - continue; - - i_next++; - } - if (!any_changes) { - while (i_next < num) { - nm_setting_ip_config_remove_route (s_ip, --num); - any_changes = TRUE; - } - } - - return any_changes; + gboolean any_changes = FALSE; + guint i_next; + guint num; + guint i; + + num = nm_setting_ip_config_get_num_routes(s_ip); + + i_next = 0; + + for (i = 0; i < entries_len; i++) { + NMIPRoute *entry = entries_arr[i]; + + if (!any_changes) { + if (i_next < num) { + if (nm_ip_route_equal_full(entry, + nm_setting_ip_config_get_route(s_ip, i_next), + NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS)) { + i_next++; + continue; + } + } + while (i_next < num) + nm_setting_ip_config_remove_route(s_ip, --num); + any_changes = TRUE; + } + + if (!nm_setting_ip_config_add_route(s_ip, entry)) + continue; + + i_next++; + } + if (!any_changes) { + while (i_next < num) { + nm_setting_ip_config_remove_route(s_ip, --num); + any_changes = TRUE; + } + } + + return any_changes; } gboolean -nmcs_setting_ip_replace_ipv4_rules (NMSettingIPConfig *s_ip, - NMIPRoutingRule **entries_arr, - guint entries_len) +nmcs_setting_ip_replace_ipv4_rules(NMSettingIPConfig *s_ip, + NMIPRoutingRule ** entries_arr, + guint entries_len) { - gboolean any_changes = FALSE; - guint i_next; - guint num; - guint i; - - num = nm_setting_ip_config_get_num_routing_rules (s_ip); - - i_next = 0; - - for (i = 0; i < entries_len; i++) { - NMIPRoutingRule *entry = entries_arr[i]; - - if (!any_changes) { - if (i_next < num) { - if (nm_ip_routing_rule_cmp (entry, - nm_setting_ip_config_get_routing_rule (s_ip, i_next)) == 0) { - i_next++; - continue; - } - } - while (i_next < num) - nm_setting_ip_config_remove_routing_rule (s_ip, --num); - any_changes = TRUE; - } - - nm_setting_ip_config_add_routing_rule (s_ip, entry); - i_next++; - } - if (!any_changes) { - while (i_next < num) { - nm_setting_ip_config_remove_routing_rule (s_ip, --num); - any_changes = TRUE; - } - } - - return any_changes; + gboolean any_changes = FALSE; + guint i_next; + guint num; + guint i; + + num = nm_setting_ip_config_get_num_routing_rules(s_ip); + + i_next = 0; + + for (i = 0; i < entries_len; i++) { + NMIPRoutingRule *entry = entries_arr[i]; + + if (!any_changes) { + if (i_next < num) { + if (nm_ip_routing_rule_cmp(entry, + nm_setting_ip_config_get_routing_rule(s_ip, i_next)) + == 0) { + i_next++; + continue; + } + } + while (i_next < num) + nm_setting_ip_config_remove_routing_rule(s_ip, --num); + any_changes = TRUE; + } + + nm_setting_ip_config_add_routing_rule(s_ip, entry); + i_next++; + } + if (!any_changes) { + while (i_next < num) { + nm_setting_ip_config_remove_routing_rule(s_ip, --num); + any_changes = TRUE; + } + } + + return any_changes; } /*****************************************************************************/ typedef struct { - GMainLoop *main_loop; - NMConnection *connection; - GError *error; - guint64 version_id; + GMainLoop * main_loop; + NMConnection *connection; + GError * error; + guint64 version_id; } DeviceGetAppliedConnectionData; static void -_nmcs_device_get_applied_connection_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) +_nmcs_device_get_applied_connection_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - DeviceGetAppliedConnectionData *data = user_data; + DeviceGetAppliedConnectionData *data = user_data; - data->connection = nm_device_get_applied_connection_finish (NM_DEVICE (source), - result, - &data->version_id, - &data->error); - g_main_loop_quit (data->main_loop); + data->connection = nm_device_get_applied_connection_finish(NM_DEVICE(source), + result, + &data->version_id, + &data->error); + g_main_loop_quit(data->main_loop); } NMConnection * -nmcs_device_get_applied_connection (NMDevice *device, - GCancellable *cancellable, - guint64 *version_id, - GError **error) +nmcs_device_get_applied_connection(NMDevice * device, + GCancellable *cancellable, + guint64 * version_id, + GError ** error) { - nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new (NULL, FALSE); - DeviceGetAppliedConnectionData data = { - .main_loop = main_loop, - }; - - nm_device_get_applied_connection_async (device, - 0, - cancellable, - _nmcs_device_get_applied_connection_cb, - &data); - - g_main_loop_run (main_loop); - - if (data.error) - g_propagate_error (error, data.error); - NM_SET_OUT (version_id, data.version_id); - return data.connection; + nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); + DeviceGetAppliedConnectionData data = { + .main_loop = main_loop, + }; + + nm_device_get_applied_connection_async(device, + 0, + cancellable, + _nmcs_device_get_applied_connection_cb, + &data); + + g_main_loop_run(main_loop); + + if (data.error) + g_propagate_error(error, data.error); + NM_SET_OUT(version_id, data.version_id); + return data.connection; } /*****************************************************************************/ typedef struct { - GMainLoop *main_loop; - GError *error; + GMainLoop *main_loop; + GError * error; } DeviceReapplyData; static void -_nmcs_device_reapply_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) +_nmcs_device_reapply_cb(GObject *source, GAsyncResult *result, gpointer user_data) { - DeviceReapplyData *data = user_data; + DeviceReapplyData *data = user_data; - nm_device_reapply_finish (NM_DEVICE (source), - result, - &data->error); - g_main_loop_quit (data->main_loop); + nm_device_reapply_finish(NM_DEVICE(source), result, &data->error); + g_main_loop_quit(data->main_loop); } gboolean -nmcs_device_reapply (NMDevice *device, - GCancellable *sigterm_cancellable, - NMConnection *connection, - guint64 version_id, - gboolean *out_version_id_changed, - GError **error) +nmcs_device_reapply(NMDevice * device, + GCancellable *sigterm_cancellable, + NMConnection *connection, + guint64 version_id, + gboolean * out_version_id_changed, + GError ** error) { - nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new (NULL, FALSE); - DeviceReapplyData data = { - .main_loop = main_loop, - }; - - nm_device_reapply_async (device, - connection, - version_id, - 0, - sigterm_cancellable, - _nmcs_device_reapply_cb, - &data); - - g_main_loop_run (main_loop); - - if (data.error) { - NM_SET_OUT (out_version_id_changed, g_error_matches (data.error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_VERSION_ID_MISMATCH)); - g_propagate_error (error, data.error); - return FALSE; - } - - NM_SET_OUT (out_version_id_changed, FALSE); - return TRUE; + nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new(NULL, FALSE); + DeviceReapplyData data = { + .main_loop = main_loop, + }; + + nm_device_reapply_async(device, + connection, + version_id, + 0, + sigterm_cancellable, + _nmcs_device_reapply_cb, + &data); + + g_main_loop_run(main_loop); + + if (data.error) { + NM_SET_OUT( + out_version_id_changed, + g_error_matches(data.error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_VERSION_ID_MISMATCH)); + g_propagate_error(error, data.error); + return FALSE; + } + + NM_SET_OUT(out_version_id_changed, FALSE); + return TRUE; } |