summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-01-04 19:20:14 +0100
committerThomas Haller <thaller@redhat.com>2021-01-08 16:32:48 +0100
commit494819bbbf973bef683e17c0a4fe0c814b6ad838 (patch)
tree698b06c5691139aec4eab476ea0ba275e72030fa
parent5fb2f7e717be727c596651f6e0ebdad4c91ecc39 (diff)
downloadNetworkManager-494819bbbf973bef683e17c0a4fe0c814b6ad838.tar.gz
cloud-setup: move common code for get_config() to base class and improve cancellation
First note that all three provider implementations are very similar. That is why NMCSProvider's implementation does already some work that is common to all implementations. For example, it provides the NMCSProviderGetConfigTaskData structure to help tracking the data of the request. Also note that the GCP/Azure implementations didn't handle the cancellation correctly. They always would pass g_task_get_cancellable(get_config_data->task) to the asynchronous requests. That is the GCancellable provider by the caller. That is fine when there is only one async operation ongoing. But that is not the case, we have parallel HTTP requests. Then, when an error happened, the overall get_config() operations fails and the still pending requests should all be aborted. However, we must not cancel the GCancellable of the user (because that is not owned by us). The correct solution is to use an internal cancellable in those cases. Anyway. Since all of this is similar, we can extend the base class to handle things for us. This also gets the cancellation right by having a "get_config_data->intern_cancellable".
-rw-r--r--clients/cloud-setup/nmcs-provider-azure.c268
-rw-r--r--clients/cloud-setup/nmcs-provider-ec2.c254
-rw-r--r--clients/cloud-setup/nmcs-provider-gcp.c183
-rw-r--r--clients/cloud-setup/nmcs-provider.c70
-rw-r--r--clients/cloud-setup/nmcs-provider.h25
5 files changed, 356 insertions, 444 deletions
diff --git a/clients/cloud-setup/nmcs-provider-azure.c b/clients/cloud-setup/nmcs-provider-azure.c
index 561eb8175a..a18a0d64b4 100644
--- a/clients/cloud-setup/nmcs-provider-azure.c
+++ b/clients/cloud-setup/nmcs-provider-azure.c
@@ -94,128 +94,87 @@ detect(NMCSProvider *provider, GTask *task)
/*****************************************************************************/
typedef struct {
- NMCSProviderGetConfigTaskData *get_config_data;
- guint n_ifaces_pending;
- GError * error;
-} AzureData;
-
-typedef struct {
+ NMCSProviderGetConfigTaskData * get_config_data;
NMCSProviderGetConfigIfaceData *iface_get_config;
- AzureData * azure_data;
gssize iface_idx;
guint n_ips_prefix_pending;
char * hwaddr;
} AzureIfaceData;
static void
-_azure_iface_data_free(AzureIfaceData *iface_data)
+_azure_iface_data_destroy(AzureIfaceData *iface_data)
{
g_free(iface_data->hwaddr);
nm_g_slice_free(iface_data);
}
static void
-_get_config_maybe_task_return(AzureData *azure_data, GError *error_take)
-{
- NMCSProviderGetConfigTaskData *get_config_data = azure_data->get_config_data;
-
- if (error_take) {
- if (!azure_data->error)
- azure_data->error = error_take;
- else if (!nm_utils_error_is_cancelled(azure_data->error)
- && nm_utils_error_is_cancelled(error_take)) {
- nm_clear_error(&azure_data->error);
- azure_data->error = error_take;
- } else
- g_error_free(error_take);
- }
-
- if (azure_data->n_ifaces_pending > 0)
- return;
-
- if (azure_data->error) {
- if (nm_utils_error_is_cancelled(azure_data->error))
- _LOGD("get-config: cancelled");
- else
- _LOGD("get-config: failed: %s", azure_data->error->message);
- g_task_return_error(get_config_data->task, g_steal_pointer(&azure_data->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_g_slice_free(azure_data);
- g_object_unref(get_config_data->task);
-}
-
-static void
-_get_config_fetch_done_cb(NMHttpClient *http_client,
- GAsyncResult *result,
- gpointer user_data,
- gboolean is_ipv4)
+_get_config_fetch_done_cb(NMHttpClient * http_client,
+ GAsyncResult * result,
+ AzureIfaceData *iface_data,
+ gboolean is_ipv4)
{
+ NMCSProviderGetConfigTaskData * get_config_data;
NMCSProviderGetConfigIfaceData *iface_get_config;
- gs_unref_bytes GBytes *response = NULL;
- AzureIfaceData * iface_data = user_data;
- gs_free_error GError *error = NULL;
- const char * fip_str = NULL;
- AzureData * azure_data;
-
- azure_data = iface_data->azure_data;
+ gs_unref_bytes GBytes *response = NULL;
+ gs_free_error GError *error = NULL;
+ const char * fip_str = NULL;
+ in_addr_t tmp_addr;
+ int tmp_prefix;
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = iface_data->get_config_data;
+
if (error)
- goto done;
+ goto out_done;
- if (!error) {
- in_addr_t tmp_addr;
- int tmp_prefix;
-
- fip_str = g_bytes_get_data(response, NULL);
- iface_data->iface_get_config =
- g_hash_table_lookup(azure_data->get_config_data->result_dict, iface_data->hwaddr);
- iface_get_config = iface_data->iface_get_config;
- iface_get_config->iface_idx = iface_data->iface_idx;
-
- if (is_ipv4) {
- if (!nm_utils_parse_inaddr_bin(AF_INET, fip_str, NULL, &tmp_addr)) {
- error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
- "ip is not a valid private ip address");
- goto done;
- }
- _LOGD("interface[%" G_GSSIZE_FORMAT "]: adding private ip %s",
- iface_data->iface_idx,
- fip_str);
- iface_get_config->ipv4s_arr[iface_get_config->ipv4s_len] = tmp_addr;
- iface_get_config->has_ipv4s = TRUE;
- iface_get_config->ipv4s_len++;
- } else {
- tmp_prefix = (_nm_utils_ascii_str_to_int64(fip_str, 10, 0, 32, -1));
-
- if (tmp_prefix == -1) {
- _LOGD("interface[%" G_GSSIZE_FORMAT "]: invalid prefix %d",
- iface_data->iface_idx,
- tmp_prefix);
- goto done;
- }
- _LOGD("interface[%" G_GSSIZE_FORMAT "]: adding prefix %d",
+ fip_str = g_bytes_get_data(response, NULL);
+ iface_data->iface_get_config =
+ g_hash_table_lookup(get_config_data->result_dict, iface_data->hwaddr);
+ iface_get_config = iface_data->iface_get_config;
+ iface_get_config->iface_idx = iface_data->iface_idx;
+
+ if (is_ipv4) {
+ if (!nm_utils_parse_inaddr_bin(AF_INET, fip_str, NULL, &tmp_addr)) {
+ error =
+ nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "ip is not a valid private ip address");
+ goto out_done;
+ }
+ _LOGD("interface[%" G_GSSIZE_FORMAT "]: adding private ip %s",
+ iface_data->iface_idx,
+ fip_str);
+ iface_get_config->ipv4s_arr[iface_get_config->ipv4s_len] = tmp_addr;
+ iface_get_config->has_ipv4s = TRUE;
+ iface_get_config->ipv4s_len++;
+ } else {
+ tmp_prefix = (_nm_utils_ascii_str_to_int64(fip_str, 10, 0, 32, -1));
+
+ if (tmp_prefix == -1) {
+ _LOGD("interface[%" G_GSSIZE_FORMAT "]: invalid prefix %d",
iface_data->iface_idx,
tmp_prefix);
- iface_get_config->cidr_prefix = tmp_prefix;
- iface_get_config->has_cidr = TRUE;
+ goto out_done;
}
+ _LOGD("interface[%" G_GSSIZE_FORMAT "]: adding prefix %d",
+ iface_data->iface_idx,
+ tmp_prefix);
+ iface_get_config->cidr_prefix = tmp_prefix;
+ iface_get_config->has_cidr = TRUE;
}
-done:
- --iface_data->n_ips_prefix_pending;
- if (iface_data->n_ips_prefix_pending == 0) {
- _azure_iface_data_free(iface_data);
- --azure_data->n_ifaces_pending;
- _get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
+out_done:
+ if (!error) {
+ --iface_data->n_ips_prefix_pending;
+ if (iface_data->n_ips_prefix_pending > 0)
+ return;
}
+
+ --get_config_data->n_pending;
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
}
static void
@@ -235,20 +194,24 @@ _get_config_fetch_done_cb_subnet_cidr_prefix(GObject * source,
static void
_get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
- gs_unref_bytes GBytes *response = NULL;
- AzureIfaceData * iface_data = user_data;
- gs_free_error GError *error = NULL;
- const char * response_str = NULL;
- gsize response_len;
- AzureData * azure_data;
- const char * line;
- gsize line_len;
-
- azure_data = iface_data->azure_data;
+ gs_unref_bytes GBytes *response = NULL;
+ AzureIfaceData * iface_data = user_data;
+ gs_free_error GError * error = NULL;
+ const char * response_str = NULL;
+ gsize response_len;
+ NMCSProviderGetConfigTaskData *get_config_data;
+ const char * line;
+ gsize line_len;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
+
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = iface_data->get_config_data;
+
if (error)
- goto done;
+ goto out_error;
response_str = g_bytes_get_data(response, &response_len);
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
@@ -293,7 +256,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
- g_task_get_cancellable(azure_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_fetch_done_cb_private_ipv4s,
@@ -319,7 +282,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
- g_task_get_cancellable(azure_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_fetch_done_cb_subnet_cidr_prefix,
@@ -327,47 +290,48 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
}
return;
-done:
- _azure_iface_data_free(iface_data);
- --azure_data->n_ifaces_pending;
- _get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
+out_error:
+ --get_config_data->n_pending;
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
}
static void
_get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
+ NMCSProviderGetConfigTaskData *get_config_data;
gs_unref_bytes GBytes *response = NULL;
AzureIfaceData * iface_data = user_data;
gs_free_error GError *error = NULL;
gs_free const char * uri = NULL;
char buf[100];
- AzureData * azure_data;
-
- azure_data = iface_data->azure_data;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = iface_data->get_config_data;
+
if (error)
- goto done;
+ goto out_done;
iface_data->hwaddr = nmcs_utils_hwaddr_normalize(g_bytes_get_data(response, NULL), -1);
- if (!iface_data->hwaddr) {
- goto done;
- }
+ if (!iface_data->hwaddr)
+ goto out_done;
iface_data->iface_get_config =
- g_hash_table_lookup(azure_data->get_config_data->result_dict, iface_data->hwaddr);
+ g_hash_table_lookup(get_config_data->result_dict, iface_data->hwaddr);
if (!iface_data->iface_get_config) {
- if (!iface_data->azure_data->get_config_data->any) {
+ if (!get_config_data->any) {
_LOGD("interface[%" G_GSSIZE_FORMAT "]: ignore hwaddr %s",
iface_data->iface_idx,
iface_data->hwaddr);
- goto done;
+ goto out_done;
}
iface_data->iface_get_config = nmcs_provider_get_config_iface_data_new(FALSE);
- g_hash_table_insert(azure_data->get_config_data->result_dict,
+ g_hash_table_insert(get_config_data->result_dict,
g_strdup(iface_data->hwaddr),
iface_data->iface_get_config);
}
@@ -385,26 +349,25 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
- g_task_get_cancellable(azure_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_ips_prefix_list_cb,
iface_data);
return;
-done:
- nm_g_slice_free(iface_data);
- --azure_data->n_ifaces_pending;
- _get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
+out_done:
+ --get_config_data->n_pending;
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
}
static void
_get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
+ NMCSProviderGetConfigTaskData *get_config_data;
gs_unref_ptrarray GPtrArray *ifaces_arr = NULL;
gs_unref_bytes GBytes *response = NULL;
gs_free_error GError *error = NULL;
- AzureData * azure_data = user_data;
const char * response_str;
gsize response_len;
const char * line;
@@ -413,8 +376,13 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = user_data;
+
if (error) {
- _get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
return;
}
@@ -422,7 +390,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
nm_assert(response_str[response_len] == 0);
- ifaces_arr = g_ptr_array_new();
+ ifaces_arr = g_ptr_array_new_with_free_func((GDestroyNotify) _azure_iface_data_destroy);
while (nm_utils_parse_next_line(&response_str, &response_len, &line, &line_len)) {
AzureIfaceData *iface_data;
@@ -444,8 +412,8 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
iface_data = g_slice_new(AzureIfaceData);
*iface_data = (AzureIfaceData){
+ .get_config_data = get_config_data,
.iface_get_config = NULL,
- .azure_data = azure_data,
.iface_idx = iface_idx,
.n_ips_prefix_pending = 0,
.hwaddr = NULL,
@@ -456,21 +424,23 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
_LOGD("found azure interfaces: %u", ifaces_arr->len);
if (ifaces_arr->len == 0) {
- error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "no Azure interfaces found");
- _get_config_maybe_task_return(azure_data, g_steal_pointer(&error));
+ _nmcs_provider_get_config_task_maybe_return(
+ get_config_data,
+ nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "no Azure interfaces found"));
return;
}
for (i = 0; i < ifaces_arr->len; ++i) {
- AzureIfaceData * data = ifaces_arr->pdata[i];
- gs_free const char *uri = NULL;
+ AzureIfaceData * iface_data = ifaces_arr->pdata[i];
+ gs_free const char *uri = NULL;
char buf[100];
- _LOGD("azure interface[%" G_GSSIZE_FORMAT "]: retrieving configuration", data->iface_idx);
+ _LOGD("azure interface[%" G_GSSIZE_FORMAT "]: retrieving configuration",
+ iface_data->iface_idx);
- nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/macAddress", data->iface_idx);
+ nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/macAddress", iface_data->iface_idx);
- azure_data->n_ifaces_pending++;
+ get_config_data->n_pending++;
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
(uri = _azure_uri_interfaces(buf)),
HTTP_TIMEOUT_MS,
@@ -478,25 +448,21 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
- g_task_get_cancellable(azure_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_iface_cb,
- data);
+ iface_data);
}
+
+ get_config_data->extra_data_destroy = (GDestroyNotify) g_ptr_array_unref;
+ get_config_data->extra_data = g_steal_pointer(&ifaces_arr);
}
static void
get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_data)
{
gs_free const char *uri = NULL;
- AzureData * azure_data;
-
- azure_data = g_slice_new(AzureData);
- *azure_data = (AzureData){
- .get_config_data = get_config_data,
- .n_ifaces_pending = 0,
- };
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
(uri = _azure_uri_interfaces()),
@@ -505,11 +471,11 @@ get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_dat
15000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
- g_task_get_cancellable(get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_net_ifaces_list_cb,
- azure_data);
+ get_config_data);
}
/*****************************************************************************/
diff --git a/clients/cloud-setup/nmcs-provider-ec2.c b/clients/cloud-setup/nmcs-provider-ec2.c
index 40bed1575c..276479f254 100644
--- a/clients/cloud-setup/nmcs-provider-ec2.c
+++ b/clients/cloud-setup/nmcs-provider-ec2.c
@@ -129,124 +129,69 @@ detect(NMCSProvider *provider, GTask *task)
/*****************************************************************************/
-typedef struct {
- NMCSProviderGetConfigTaskData *get_config_data;
- GError * error;
- GCancellable * cancellable;
- gulong cancelled_id;
- guint n_pending;
-} GetConfigIfaceData;
-
static void
-_get_config_task_maybe_return(GetConfigIfaceData *iface_data, GError *error_take)
+_get_config_fetch_done_cb(NMHttpClient *http_client,
+ GAsyncResult *result,
+ gpointer user_data,
+ gboolean is_local_ipv4)
{
- NMCSProviderGetConfigTaskData *get_config_data = iface_data->get_config_data;
-
- if (error_take) {
- if (!iface_data->error)
- iface_data->error = error_take;
- else if (!nm_utils_error_is_cancelled(iface_data->error)
- && nm_utils_error_is_cancelled(error_take)) {
- nm_clear_error(&iface_data->error);
- iface_data->error = error_take;
- } else
- g_error_free(error_take);
-
- nm_clear_g_cancellable(&iface_data->cancellable);
- }
+ NMCSProviderGetConfigTaskData *get_config_data;
+ const char * hwaddr = NULL;
+ gs_unref_bytes GBytes *response = NULL;
+ gs_free_error GError * error = NULL;
+ NMCSProviderGetConfigIfaceData *config_iface_data;
+ in_addr_t tmp_addr;
+ int tmp_prefix;
- if (iface_data->n_pending > 0)
- return;
+ nm_utils_user_data_unpack(user_data, &get_config_data, &hwaddr);
- nm_clear_g_cancellable_disconnect(g_task_get_cancellable(get_config_data->task),
- &iface_data->cancelled_id);
+ nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
- nm_clear_g_cancellable(&iface_data->cancellable);
+ if (nm_utils_error_is_cancelled(error))
+ return;
- if (iface_data->error) {
- if (nm_utils_error_is_cancelled(iface_data->error))
- _LOGD("get-config: cancelled");
- else
- _LOGD("get-config: failed: %s", iface_data->error->message);
- g_task_return_error(get_config_data->task, g_steal_pointer(&iface_data->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);
- }
+ if (error)
+ goto out;
- nm_g_slice_free(iface_data);
- g_object_unref(get_config_data->task);
-}
+ config_iface_data = g_hash_table_lookup(get_config_data->result_dict, hwaddr);
-static void
-_get_config_fetch_done_cb(NMHttpClient *http_client,
- GAsyncResult *result,
- gpointer user_data,
- gboolean is_local_ipv4)
-{
- GetConfigIfaceData *iface_data;
- const char * hwaddr = NULL;
- gs_unref_bytes GBytes *response = NULL;
- gs_free_error GError *error = NULL;
+ if (is_local_ipv4) {
+ gs_free const char **s_addrs = NULL;
+ gsize i, len;
- nm_utils_user_data_unpack(user_data, &iface_data, &hwaddr);
+ s_addrs = nm_utils_strsplit_set_full(g_bytes_get_data(response, NULL),
+ "\n",
+ NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
+ len = NM_PTRARRAY_LEN(s_addrs);
- nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
+ nm_assert(!config_iface_data->has_ipv4s);
+ nm_assert(!config_iface_data->ipv4s_arr);
+ config_iface_data->has_ipv4s = TRUE;
+ config_iface_data->ipv4s_len = 0;
+ if (len > 0) {
+ config_iface_data->ipv4s_arr = g_new(in_addr_t, len);
- if (!error) {
- NMCSProviderGetConfigIfaceData *config_iface_data;
- in_addr_t tmp_addr;
- int tmp_prefix;
-
- config_iface_data = g_hash_table_lookup(iface_data->get_config_data->result_dict, hwaddr);
-
- if (is_local_ipv4) {
- gs_free const char **s_addrs = NULL;
- gsize i, len;
-
- s_addrs = nm_utils_strsplit_set_full(g_bytes_get_data(response, NULL),
- "\n",
- NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
- len = NM_PTRARRAY_LEN(s_addrs);
-
- nm_assert(!config_iface_data->has_ipv4s);
- nm_assert(!config_iface_data->ipv4s_arr);
- config_iface_data->has_ipv4s = TRUE;
- config_iface_data->ipv4s_len = 0;
- if (len > 0) {
- config_iface_data->ipv4s_arr = g_new(in_addr_t, len);
-
- for (i = 0; i < len; i++) {
- if (nm_utils_parse_inaddr_bin(AF_INET, s_addrs[i], NULL, &tmp_addr))
- config_iface_data->ipv4s_arr[config_iface_data->ipv4s_len++] = tmp_addr;
- }
- }
- } else {
- if (nm_utils_parse_inaddr_prefix_bin(AF_INET,
- g_bytes_get_data(response, NULL),
- NULL,
- &tmp_addr,
- &tmp_prefix)) {
- nm_assert(!config_iface_data->has_cidr);
- config_iface_data->has_cidr = TRUE;
- config_iface_data->cidr_prefix = tmp_prefix;
- config_iface_data->cidr_addr = tmp_addr;
+ for (i = 0; i < len; i++) {
+ if (nm_utils_parse_inaddr_bin(AF_INET, s_addrs[i], NULL, &tmp_addr))
+ config_iface_data->ipv4s_arr[config_iface_data->ipv4s_len++] = tmp_addr;
}
}
+ } else {
+ if (nm_utils_parse_inaddr_prefix_bin(AF_INET,
+ g_bytes_get_data(response, NULL),
+ NULL,
+ &tmp_addr,
+ &tmp_prefix)) {
+ nm_assert(!config_iface_data->has_cidr);
+ config_iface_data->has_cidr = TRUE;
+ config_iface_data->cidr_prefix = tmp_prefix;
+ config_iface_data->cidr_addr = tmp_addr;
+ }
}
- /* If nm_utils_error_is_cancelled(error), then our internal iface_data->cancellable
- * was cancelled, because the overall request failed. From point of view of the
- * caller, this does not mean that a cancellation happened. It also means, our
- * request overall is already about to fail. */
- nm_assert(!nm_utils_error_is_cancelled(error) || iface_data->error);
-
- iface_data->n_pending--;
- _get_config_task_maybe_return(iface_data,
- nm_utils_error_is_cancelled(error) ? NULL
- : g_steal_pointer(&error));
+out:
+ get_config_data->n_pending--;
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
}
static void
@@ -263,21 +208,6 @@ _get_config_fetch_done_cb_local_ipv4s(GObject *source, GAsyncResult *result, gpo
_get_config_fetch_done_cb(NM_HTTP_CLIENT(source), result, user_data, TRUE);
}
-static void
-_get_config_fetch_cancelled_cb(GObject *object, gpointer user_data)
-{
- GetConfigIfaceData *iface_data = user_data;
-
- nm_clear_g_signal_handler(g_task_get_cancellable(iface_data->get_config_data->task),
- &iface_data->cancelled_id);
- _get_config_task_maybe_return(iface_data, nm_utils_error_new_cancelled(FALSE, NULL));
-}
-
-typedef struct {
- NMCSProviderGetConfigTaskData *get_config_data;
- GHashTable * response_parsed;
-} GetConfigMetadataData;
-
typedef struct {
gssize iface_idx;
char path[0];
@@ -286,60 +216,33 @@ typedef struct {
static void
_get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
- GetConfigMetadataData * metadata_data = user_data;
- GetConfigIfaceData * iface_data;
- NMCSProviderGetConfigTaskData *get_config_data = metadata_data->get_config_data;
- gs_unref_hashtable GHashTable *response_parsed =
- g_steal_pointer(&metadata_data->response_parsed);
- gs_free_error GError *error = NULL;
- GCancellable * cancellable;
+ NMCSProviderGetConfigTaskData *get_config_data;
+ gs_unref_hashtable GHashTable *response_parsed = NULL;
+ gs_free_error GError *error = NULL;
GetConfigMetadataMac *v_mac_data;
const char * v_hwaddr;
GHashTableIter h_iter;
NMHttpClient * http_client;
- nm_g_slice_free(metadata_data);
-
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &error);
- iface_data = g_slice_new(GetConfigIfaceData);
- *iface_data = (GetConfigIfaceData){
- .get_config_data = get_config_data,
- .n_pending = 0,
- };
-
- if (nm_utils_error_is_cancelled(error)) {
- _get_config_task_maybe_return(iface_data, g_steal_pointer(&error));
+ if (nm_utils_error_is_cancelled(error))
return;
- }
+
+ get_config_data = user_data;
+
+ response_parsed = g_steal_pointer(&get_config_data->extra_data);
+ get_config_data->extra_data_destroy = NULL;
/* We ignore errors. Only if we got no response at all, it's a problem.
* Otherwise, we proceed with whatever we could fetch. */
if (!response_parsed) {
- _get_config_task_maybe_return(
- iface_data,
+ _nmcs_provider_get_config_task_maybe_return(
+ get_config_data,
nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "meta data for interfaces not found"));
return;
}
- cancellable = g_task_get_cancellable(get_config_data->task);
- if (cancellable) {
- gulong cancelled_id;
-
- cancelled_id = g_cancellable_connect(cancellable,
- G_CALLBACK(_get_config_fetch_cancelled_cb),
- iface_data,
- NULL);
- if (cancelled_id == 0) {
- /* the callback was already invoked synchronously and the task already returned. */
- return;
- }
-
- iface_data->cancelled_id = cancelled_id;
- }
-
- iface_data->cancellable = g_cancellable_new();
-
http_client = nmcs_provider_get_http_client(g_task_get_source_object(get_config_data->task));
g_hash_table_iter_init(&h_iter, response_parsed);
@@ -373,7 +276,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
hwaddr,
v_mac_data->path);
- iface_data->n_pending++;
+ get_config_data->n_pending++;
nm_http_client_poll_get(
http_client,
(uri1 = _ec2_uri_interfaces(v_mac_data->path,
@@ -384,13 +287,13 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
10000,
1000,
NULL,
- iface_data->cancellable,
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_fetch_done_cb_subnet_ipv4_cidr_block,
- nm_utils_user_data_pack(iface_data, hwaddr));
+ nm_utils_user_data_pack(get_config_data, hwaddr));
- iface_data->n_pending++;
+ get_config_data->n_pending++;
nm_http_client_poll_get(
http_client,
(uri2 = _ec2_uri_interfaces(v_mac_data->path,
@@ -401,14 +304,14 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
10000,
1000,
NULL,
- iface_data->cancellable,
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_fetch_done_cb_local_ipv4s,
- nm_utils_user_data_pack(iface_data, hwaddr));
+ nm_utils_user_data_pack(get_config_data, hwaddr));
}
- _get_config_task_maybe_return(iface_data, NULL);
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, NULL);
}
static gboolean
@@ -417,7 +320,7 @@ _get_config_metadata_ready_check(long response_code,
gpointer check_user_data,
GError **error)
{
- GetConfigMetadataData *metadata_data = check_user_data;
+ NMCSProviderGetConfigTaskData *get_config_data = check_user_data;
gs_unref_hashtable GHashTable *response_parsed = NULL;
const guint8 * r_data;
const char * cur_line;
@@ -465,7 +368,7 @@ _get_config_metadata_ready_check(long response_code,
}
has_all = TRUE;
- g_hash_table_iter_init(&h_iter, metadata_data->get_config_data->result_dict);
+ g_hash_table_iter_init(&h_iter, get_config_data->result_dict);
while (g_hash_table_iter_next(&h_iter, (gpointer *) &c_hwaddr, NULL)) {
if (!response_parsed || !g_hash_table_contains(response_parsed, c_hwaddr)) {
has_all = FALSE;
@@ -473,21 +376,18 @@ _get_config_metadata_ready_check(long response_code,
}
}
- nm_clear_pointer(&metadata_data->response_parsed, g_hash_table_unref);
- metadata_data->response_parsed = g_steal_pointer(&response_parsed);
+ nm_clear_pointer(&get_config_data->extra_data, g_hash_table_unref);
+ if (response_parsed) {
+ get_config_data->extra_data = g_steal_pointer(&response_parsed);
+ get_config_data->extra_data_destroy = (GDestroyNotify) g_hash_table_unref;
+ }
return has_all;
}
static void
get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_data)
{
- gs_free char * uri = NULL;
- GetConfigMetadataData *metadata_data;
-
- metadata_data = g_slice_new(GetConfigMetadataData);
- *metadata_data = (GetConfigMetadataData){
- .get_config_data = get_config_data,
- };
+ gs_free char *uri = NULL;
/* First we fetch the "macs/". If the caller requested some particular
* MAC addresses, then we poll until we see them. They might not yet be
@@ -500,11 +400,11 @@ get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_dat
15000,
1000,
NULL,
- g_task_get_cancellable(get_config_data->task),
+ get_config_data->intern_cancellable,
_get_config_metadata_ready_check,
- metadata_data,
+ get_config_data,
_get_config_metadata_ready_cb,
- metadata_data);
+ get_config_data);
}
/*****************************************************************************/
diff --git a/clients/cloud-setup/nmcs-provider-gcp.c b/clients/cloud-setup/nmcs-provider-gcp.c
index 45e1c3622b..a8b50f98f7 100644
--- a/clients/cloud-setup/nmcs-provider-gcp.c
+++ b/clients/cloud-setup/nmcs-provider-gcp.c
@@ -89,57 +89,22 @@ detect(NMCSProvider *provider, GTask *task)
/*****************************************************************************/
typedef struct {
- NMCSProviderGetConfigTaskData *get_config_data;
- guint n_ifaces_pending;
- GError * error;
-} GCPData;
-
-typedef struct {
+ NMCSProviderGetConfigTaskData * get_config_data;
NMCSProviderGetConfigIfaceData *iface_get_config;
- GCPData * gcp_data;
gssize iface_idx;
guint n_fips_pending;
} GCPIfaceData;
static void
-_get_config_maybe_task_return(GCPData *gcp_data, GError *error_take)
+_gcp_iface_data_destroy(GCPIfaceData *iface_data)
{
- NMCSProviderGetConfigTaskData *get_config_data = gcp_data->get_config_data;
-
- if (error_take) {
- if (!gcp_data->error)
- gcp_data->error = error_take;
- else if (!nm_utils_error_is_cancelled(gcp_data->error)
- && nm_utils_error_is_cancelled(error_take)) {
- nm_clear_error(&gcp_data->error);
- gcp_data->error = error_take;
- } else
- g_error_free(error_take);
- }
-
- if (gcp_data->n_ifaces_pending > 0)
- return;
-
- if (gcp_data->error) {
- if (nm_utils_error_is_cancelled(gcp_data->error))
- _LOGD("get-config: cancelled");
- else
- _LOGD("get-config: failed: %s", gcp_data->error->message);
- g_task_return_error(get_config_data->task, g_steal_pointer(&gcp_data->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_g_slice_free(gcp_data);
- g_object_unref(get_config_data->task);
+ nm_g_slice_free(iface_data);
}
static void
_get_config_fip_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
+ NMCSProviderGetConfigTaskData * get_config_data;
NMCSProviderGetConfigIfaceData *iface_get_config;
gs_unref_bytes GBytes *response = NULL;
GCPIfaceData * iface_data = user_data;
@@ -147,20 +112,22 @@ _get_config_fip_cb(GObject *source, GAsyncResult *result, gpointer user_data)
const char * fip_str = NULL;
NMIPRoute ** routes_arr;
NMIPRoute * route_new;
- GCPData * gcp_data;
-
- gcp_data = iface_data->gcp_data;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = iface_data->get_config_data;
+
if (error)
- goto iface_done;
+ goto out_done;
fip_str = g_bytes_get_data(response, NULL);
if (!nm_utils_ipaddr_valid(AF_INET, fip_str)) {
error =
nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "forwarded-ip is not a valid ip address");
- goto iface_done;
+ goto out_done;
}
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: adding forwarded-ip %s",
@@ -173,42 +140,46 @@ _get_config_fip_cb(GObject *source, GAsyncResult *result, gpointer user_data)
route_new = nm_ip_route_new(AF_INET, fip_str, 32, NULL, 100, &error);
if (error)
- goto iface_done;
+ goto out_done;
nm_ip_route_set_attribute(route_new, NM_IP_ROUTE_ATTRIBUTE_TYPE, g_variant_new_string("local"));
routes_arr[iface_get_config->iproutes_len] = route_new;
++iface_get_config->iproutes_len;
-iface_done:
- --iface_data->n_fips_pending;
- if (iface_data->n_fips_pending == 0) {
- nm_g_slice_free(iface_data);
- --gcp_data->n_ifaces_pending;
+out_done:
+ if (!error) {
+ --iface_data->n_fips_pending;
+ if (iface_data->n_fips_pending > 0)
+ return;
}
- _get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
+ --get_config_data->n_pending;
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
}
static void
_get_config_ips_list_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
+ NMCSProviderGetConfigTaskData *get_config_data;
gs_unref_ptrarray GPtrArray *uri_arr = NULL;
gs_unref_bytes GBytes *response = NULL;
GCPIfaceData * iface_data = user_data;
gs_free_error GError *error = NULL;
const char * response_str = NULL;
gsize response_len;
- GCPData * gcp_data;
const char * line;
gsize line_len;
guint i;
- gcp_data = iface_data->gcp_data;
-
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = iface_data->get_config_data;
+
if (error)
- goto fips_error;
+ goto out_error;
response_str = g_bytes_get_data(response, &response_len);
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
@@ -240,7 +211,7 @@ _get_config_ips_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
if (iface_data->n_fips_pending == 0) {
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "found no forwarded ip");
- goto fips_error;
+ goto out_error;
}
iface_data->iface_get_config->iproutes_arr = g_new(NMIPRoute *, iface_data->n_fips_pending);
@@ -256,7 +227,7 @@ _get_config_ips_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
- g_task_get_cancellable(gcp_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_fip_cb,
@@ -264,39 +235,40 @@ _get_config_ips_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
}
return;
-fips_error:
- nm_g_slice_free(iface_data);
- --gcp_data->n_ifaces_pending;
- _get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
+out_error:
+ --get_config_data->n_pending;
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
}
static void
_get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
- gs_unref_bytes GBytes *response = NULL;
- GCPIfaceData * iface_data = user_data;
- gs_free_error GError *error = NULL;
- gs_free const char * hwaddr = NULL;
- gs_free const char * uri = NULL;
- char sbuf[100];
- GCPData * gcp_data;
-
- gcp_data = iface_data->gcp_data;
+ gs_unref_bytes GBytes *response = NULL;
+ GCPIfaceData * iface_data = user_data;
+ gs_free_error GError * error = NULL;
+ gs_free const char * hwaddr = NULL;
+ gs_free const char * uri = NULL;
+ char sbuf[100];
+ NMCSProviderGetConfigTaskData *get_config_data;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = iface_data->get_config_data;
+
if (error)
- goto iface_error;
+ goto out_error;
hwaddr = nmcs_utils_hwaddr_normalize(g_bytes_get_data(response, NULL), -1);
- iface_data->iface_get_config =
- g_hash_table_lookup(gcp_data->get_config_data->result_dict, hwaddr);
+ iface_data->iface_get_config = g_hash_table_lookup(get_config_data->result_dict, hwaddr);
if (!iface_data->iface_get_config) {
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: did not find a matching device",
iface_data->iface_idx);
error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN,
"no matching hwaddr found for GCP interface");
- goto iface_error;
+ goto out_error;
}
_LOGI("GCP interface[%" G_GSSIZE_FORMAT "]: found a matching device with hwaddr %s",
@@ -312,17 +284,16 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
- g_task_get_cancellable(gcp_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_ips_list_cb,
iface_data);
return;
-iface_error:
- nm_g_slice_free(iface_data);
- --gcp_data->n_ifaces_pending;
- _get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
+out_error:
+ --get_config_data->n_pending;
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
}
static void
@@ -330,18 +301,23 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
{
gs_unref_ptrarray GPtrArray *ifaces_arr = NULL;
gs_unref_bytes GBytes *response = NULL;
- gs_free_error GError *error = NULL;
- GCPData * gcp_data = user_data;
- const char * response_str;
- gsize response_len;
- const char * line;
- gsize line_len;
- guint i;
+ gs_free_error GError * error = NULL;
+ NMCSProviderGetConfigTaskData *get_config_data;
+ const char * response_str;
+ gsize response_len;
+ const char * line;
+ gsize line_len;
+ guint i;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
+ if (nm_utils_error_is_cancelled(error))
+ return;
+
+ get_config_data = user_data;
+
if (error) {
- _get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
+ _nmcs_provider_get_config_task_maybe_return(get_config_data, g_steal_pointer(&error));
return;
}
@@ -349,7 +325,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
/* NMHttpClient guarantees that there is a trailing NUL after the data. */
nm_assert(response_str[response_len] == 0);
- ifaces_arr = g_ptr_array_new();
+ ifaces_arr = g_ptr_array_new_with_free_func((GDestroyNotify) _gcp_iface_data_destroy);
while (nm_utils_parse_next_line(&response_str, &response_len, &line, &line_len)) {
GCPIfaceData *iface_data;
@@ -370,17 +346,23 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
iface_data = g_slice_new(GCPIfaceData);
*iface_data = (GCPIfaceData){
+ .get_config_data = get_config_data,
.iface_get_config = NULL,
- .gcp_data = gcp_data,
.iface_idx = iface_idx,
.n_fips_pending = 0,
};
g_ptr_array_add(ifaces_arr, iface_data);
}
- gcp_data->n_ifaces_pending = ifaces_arr->len;
_LOGI("found GCP interfaces: %u", ifaces_arr->len);
+ if (ifaces_arr->len == 0) {
+ _nmcs_provider_get_config_task_maybe_return(
+ get_config_data,
+ nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "no GCP interfaces found"));
+ return;
+ }
+
for (i = 0; i < ifaces_arr->len; ++i) {
GCPIfaceData * data = ifaces_arr->pdata[i];
gs_free const char *uri = NULL;
@@ -390,6 +372,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
nm_sprintf_buf(sbuf, "%" G_GSSIZE_FORMAT "/mac", data->iface_idx);
+ get_config_data->n_pending++;
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
(uri = _gcp_uri_interfaces(sbuf)),
HTTP_TIMEOUT_MS,
@@ -397,31 +380,21 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
- g_task_get_cancellable(gcp_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_config_iface_cb,
data);
}
- if (ifaces_arr->len == 0) {
- error = nm_utils_error_new(NM_UTILS_ERROR_UNKNOWN, "no GCP interfaces found");
- _get_config_maybe_task_return(gcp_data, g_steal_pointer(&error));
- }
+ get_config_data->extra_data = g_steal_pointer(&ifaces_arr);
+ get_config_data->extra_data_destroy = (GDestroyNotify) g_ptr_array_unref;
}
static void
get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_data)
{
gs_free const char *uri = NULL;
- GCPData * gcp_data;
-
- gcp_data = g_slice_new(GCPData);
- *gcp_data = (GCPData){
- .get_config_data = get_config_data,
- .n_ifaces_pending = 0,
- .error = NULL,
- };
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
(uri = _gcp_uri_interfaces()),
@@ -430,11 +403,11 @@ get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_dat
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
- g_task_get_cancellable(gcp_data->get_config_data->task),
+ get_config_data->intern_cancellable,
NULL,
NULL,
_get_net_ifaces_list_cb,
- gcp_data);
+ get_config_data);
}
/*****************************************************************************/
diff --git a/clients/cloud-setup/nmcs-provider.c b/clients/cloud-setup/nmcs-provider.c
index 9fac4b6679..6512b76faf 100644
--- a/clients/cloud-setup/nmcs-provider.c
+++ b/clients/cloud-setup/nmcs-provider.c
@@ -114,19 +114,61 @@ _iface_data_free(gpointer data)
}
static void
-_get_config_data_free(gpointer data)
+_get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data, GError *error_take)
{
- NMCSProviderGetConfigTaskData *get_config_data = data;
+ gs_free_error GError *error = error_take;
- if (get_config_data->extra_destroy)
- get_config_data->extra_destroy(get_config_data->extra_data);
+ 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,
@@ -139,6 +181,8 @@ nmcs_provider_get_config(NMCSProvider * self,
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),
@@ -146,8 +190,6 @@ nmcs_provider_get_config(NMCSProvider * self,
.result_dict = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _iface_data_free),
};
- g_task_set_task_data(get_config_data->task, get_config_data, _get_config_data_free);
-
nmcs_wait_for_objects_register(get_config_data->task);
for (; hwaddrs && hwaddrs[0]; hwaddrs++) {
@@ -156,7 +198,21 @@ nmcs_provider_get_config(NMCSProvider * self,
nmcs_provider_get_config_iface_data_new(TRUE));
}
- _LOGD("get-config: starting");
+ 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);
}
diff --git a/clients/cloud-setup/nmcs-provider.h b/clients/cloud-setup/nmcs-provider.h
index a26c6a366b..3edd874337 100644
--- a/clients/cloud-setup/nmcs-provider.h
+++ b/clients/cloud-setup/nmcs-provider.h
@@ -37,11 +37,25 @@ nmcs_provider_get_config_iface_data_is_valid(const NMCSProviderGetConfigIfaceDat
NMCSProviderGetConfigIfaceData *nmcs_provider_get_config_iface_data_new(gboolean was_requested);
typedef struct {
- GTask * task;
- GHashTable * result_dict;
+ GTask *task;
+
+ GHashTable *result_dict;
+
+ /* this cancellable should be used for the provider implementation
+ * to listen for cancellation. */
+ GCancellable *intern_cancellable;
+
+ /* the provider implementation may attach extra data. */
gpointer extra_data;
- GDestroyNotify extra_destroy;
- bool any : 1;
+ GDestroyNotify extra_data_destroy;
+
+ gulong extern_cancelled_id;
+
+ /* the provider implementation may use this field to track the number of pending
+ * operations. */
+ guint n_pending;
+
+ bool any : 1;
} NMCSProviderGetConfigTaskData;
#define NMCS_TYPE_PROVIDER (nmcs_provider_get_type())
@@ -93,6 +107,9 @@ gboolean nmcs_provider_detect_finish(NMCSProvider *provider, GAsyncResult *resul
/*****************************************************************************/
+void _nmcs_provider_get_config_task_maybe_return(NMCSProviderGetConfigTaskData *get_config_data,
+ GError * error_take);
+
void nmcs_provider_get_config(NMCSProvider * provider,
gboolean any,
const char *const * hwaddrs,