Lubomir Rintel 2023-03-08 12:09:13 +01:00
commit c739ebaf4b
7 changed files with 224 additions and 146 deletions

View file

@ -104,12 +104,12 @@ typedef struct {
} GetResult;
static void
_get_result_free(gpointer data)
_req_result_free(gpointer data)
{
GetResult *get_result = data;
GetResult *req_result = data;
g_bytes_unref(get_result->response_data);
nm_g_slice_free(get_result);
g_bytes_unref(req_result->response_data);
nm_g_slice_free(req_result);
}
typedef struct {
@ -154,7 +154,7 @@ _ehandle_free(EHandleData *edata)
static void
_ehandle_complete(EHandleData *edata, GError *error_take)
{
GetResult *get_result;
GetResult *req_result;
gs_free char *str_tmp_1 = NULL;
long response_code = -1;
@ -200,15 +200,15 @@ _ehandle_complete(EHandleData *edata, GError *error_take)
_ehandle_free_ehandle(edata);
get_result = g_slice_new(GetResult);
*get_result = (GetResult){
req_result = g_slice_new(GetResult);
*req_result = (GetResult){
.response_code = response_code,
/* This ensures that response_data is always NUL terminated. This is an important guarantee
* that NMHttpClient makes. */
.response_data = nm_str_buf_finalize_to_gbytes(&edata->recv_data),
};
g_task_return_pointer(edata->task, get_result, _get_result_free);
g_task_return_pointer(edata->task, req_result, _req_result_free);
_ehandle_free(edata);
}
@ -256,12 +256,13 @@ _get_cancelled_cb(GObject *object, gpointer user_data)
_ehandle_complete(edata, error);
}
void
nm_http_client_get(NMHttpClient *self,
static void
nm_http_client_req(NMHttpClient *self,
const char *url,
int timeout_msec,
gssize max_data,
const char *const *http_headers,
const char *http_method,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@ -280,7 +281,7 @@ nm_http_client_get(NMHttpClient *self,
edata = g_slice_new(EHandleData);
*edata = (EHandleData){
.task = nm_g_task_new(self, cancellable, nm_http_client_get, callback, user_data),
.task = nm_g_task_new(self, cancellable, nm_http_client_req, callback, user_data),
.recv_data = NM_STR_BUF_INIT(0, FALSE),
.max_data = max_data,
.url = g_strdup(url),
@ -328,6 +329,9 @@ nm_http_client_get(NMHttpClient *self,
curl_easy_setopt(edata->ehandle, CURLOPT_HTTPHEADER, edata->headers);
}
if (http_method)
curl_easy_setopt(edata->ehandle, CURLOPT_CUSTOMREQUEST, http_method);
if (timeout_msec > 0) {
edata->timeout_source = _source_attach(self,
nm_g_timeout_source_new(timeout_msec,
@ -352,7 +356,7 @@ nm_http_client_get(NMHttpClient *self,
}
/**
* nm_http_client_get_finish:
* nm_http_client_req_finish:
* @self: the #NMHttpClient instance
* @result: the #GAsyncResult which to complete.
* @out_response_code: (allow-none) (out): the HTTP response code or -1 on other error.
@ -366,34 +370,34 @@ nm_http_client_get(NMHttpClient *self,
*
* Returns: %TRUE on success or %FALSE with an error code.
*/
gboolean
nm_http_client_get_finish(NMHttpClient *self,
static gboolean
nm_http_client_req_finish(NMHttpClient *self,
GAsyncResult *result,
long *out_response_code,
GBytes **out_response_data,
GError **error)
{
GetResult *get_result;
GetResult *req_result;
g_return_val_if_fail(NM_IS_HTTP_CLIENT(self), FALSE);
g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_get), FALSE);
g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_req), FALSE);
get_result = g_task_propagate_pointer(G_TASK(result), error);
req_result = g_task_propagate_pointer(G_TASK(result), error);
nm_assert(!error || (!!get_result) == (!*error));
nm_assert(!error || (!!req_result) == (!*error));
if (!get_result) {
if (!req_result) {
NM_SET_OUT(out_response_code, -1);
NM_SET_OUT(out_response_data, NULL);
return FALSE;
}
NM_SET_OUT(out_response_code, get_result->response_code);
NM_SET_OUT(out_response_code, req_result->response_code);
/* response_data is binary, but is also guaranteed to be NUL terminated! */
NM_SET_OUT(out_response_data, g_steal_pointer(&get_result->response_data));
NM_SET_OUT(out_response_data, g_steal_pointer(&req_result->response_data));
_get_result_free(get_result);
_req_result_free(req_result);
return TRUE;
}
@ -403,63 +407,65 @@ typedef struct {
GTask *task;
char *uri;
const char *const *http_headers;
NMHttpClientPollGetCheckFcn check_fcn;
const char *http_method;
NMHttpClientPollReqCheckFcn check_fcn;
gpointer check_user_data;
GBytes *response_data;
gsize request_max_data;
long response_code;
int request_timeout_ms;
} PollGetData;
} PollReqData;
static void
_poll_get_data_free(gpointer data)
_poll_req_data_free(gpointer data)
{
PollGetData *poll_get_data = data;
PollReqData *poll_req_data = data;
g_free(poll_get_data->uri);
g_free(poll_req_data->uri);
nm_clear_pointer(&poll_get_data->response_data, g_bytes_unref);
g_free((gpointer) poll_get_data->http_headers);
nm_clear_pointer(&poll_req_data->response_data, g_bytes_unref);
g_free((gpointer) poll_req_data->http_headers);
nm_g_slice_free(poll_get_data);
nm_g_slice_free(poll_req_data);
}
static void
_poll_get_probe_start_fcn(GCancellable *cancellable,
_poll_req_probe_start_fcn(GCancellable *cancellable,
gpointer probe_user_data,
GAsyncReadyCallback callback,
gpointer user_data)
{
PollGetData *poll_get_data = probe_user_data;
PollReqData *poll_req_data = probe_user_data;
/* balanced by _poll_get_probe_finish_fcn() */
g_object_ref(poll_get_data->task);
/* balanced by _poll_req_probe_finish_fcn() */
g_object_ref(poll_req_data->task);
nm_http_client_get(g_task_get_source_object(poll_get_data->task),
poll_get_data->uri,
poll_get_data->request_timeout_ms,
poll_get_data->request_max_data,
poll_get_data->http_headers,
nm_http_client_req(g_task_get_source_object(poll_req_data->task),
poll_req_data->uri,
poll_req_data->request_timeout_ms,
poll_req_data->request_max_data,
poll_req_data->http_headers,
poll_req_data->http_method,
cancellable,
callback,
user_data);
}
static gboolean
_poll_get_probe_finish_fcn(GObject *source,
_poll_req_probe_finish_fcn(GObject *source,
GAsyncResult *result,
gpointer probe_user_data,
GError **error)
{
PollGetData *poll_get_data = probe_user_data;
PollReqData *poll_req_data = probe_user_data;
_nm_unused gs_unref_object GTask *task =
poll_get_data->task; /* balance ref from _poll_get_probe_start_fcn() */
poll_req_data->task; /* balance ref from _poll_req_probe_start_fcn() */
gboolean success;
gs_free_error GError *local_error = NULL;
gs_unref_bytes GBytes *response_data = NULL;
long response_code = -1;
success = nm_http_client_get_finish(g_task_get_source_object(poll_get_data->task),
success = nm_http_client_req_finish(g_task_get_source_object(poll_req_data->task),
result,
&response_code,
&response_data,
@ -476,10 +482,10 @@ _poll_get_probe_finish_fcn(GObject *source,
return FALSE;
}
if (poll_get_data->check_fcn) {
success = poll_get_data->check_fcn(response_code,
if (poll_req_data->check_fcn) {
success = poll_req_data->check_fcn(response_code,
response_data,
poll_get_data->check_user_data,
poll_req_data->check_user_data,
&local_error);
} else
success = (response_code == 200);
@ -494,15 +500,15 @@ _poll_get_probe_finish_fcn(GObject *source,
return FALSE;
}
poll_get_data->response_code = response_code;
poll_get_data->response_data = g_steal_pointer(&response_data);
poll_req_data->response_code = response_code;
poll_req_data->response_data = g_steal_pointer(&response_data);
return TRUE;
}
static void
_poll_get_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
_poll_req_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
PollGetData *poll_get_data = user_data;
PollReqData *poll_req_data = user_data;
gs_free_error GError *error = NULL;
gboolean success;
@ -511,29 +517,30 @@ _poll_get_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
nm_assert((!!success) == (!error));
if (error)
g_task_return_error(poll_get_data->task, g_steal_pointer(&error));
g_task_return_error(poll_req_data->task, g_steal_pointer(&error));
else
g_task_return_boolean(poll_get_data->task, TRUE);
g_task_return_boolean(poll_req_data->task, TRUE);
g_object_unref(poll_get_data->task);
g_object_unref(poll_req_data->task);
}
void
nm_http_client_poll_get(NMHttpClient *self,
nm_http_client_poll_req(NMHttpClient *self,
const char *uri,
int request_timeout_ms,
gssize request_max_data,
int poll_timeout_ms,
int ratelimit_timeout_ms,
const char *const *http_headers,
const char *http_method,
GCancellable *cancellable,
NMHttpClientPollGetCheckFcn check_fcn,
NMHttpClientPollReqCheckFcn check_fcn,
gpointer check_user_data,
GAsyncReadyCallback callback,
gpointer user_data)
{
nm_auto_pop_gmaincontext GMainContext *context = NULL;
PollGetData *poll_get_data;
PollReqData *poll_req_data;
g_return_if_fail(NM_IS_HTTP_CLIENT(self));
g_return_if_fail(uri && uri[0]);
@ -543,9 +550,9 @@ nm_http_client_poll_get(NMHttpClient *self,
g_return_if_fail(ratelimit_timeout_ms >= -1);
g_return_if_fail(!cancellable || G_CANCELLABLE(cancellable));
poll_get_data = g_slice_new(PollGetData);
*poll_get_data = (PollGetData){
.task = nm_g_task_new(self, cancellable, nm_http_client_poll_get, callback, user_data),
poll_req_data = g_slice_new(PollReqData);
*poll_req_data = (PollReqData){
.task = nm_g_task_new(self, cancellable, nm_http_client_poll_req, callback, user_data),
.uri = g_strdup(uri),
.request_timeout_ms = request_timeout_ms,
.request_max_data = request_max_data,
@ -556,13 +563,13 @@ nm_http_client_poll_get(NMHttpClient *self,
};
if (http_headers) {
poll_get_data->http_headers =
poll_req_data->http_headers =
nm_strv_dup_packed(http_headers, -1) ?: g_new(const char *, 1);
}
nmcs_wait_for_objects_register(poll_get_data->task);
nmcs_wait_for_objects_register(poll_req_data->task);
g_task_set_task_data(poll_get_data->task, poll_get_data, _poll_get_data_free);
g_task_set_task_data(poll_req_data->task, poll_req_data, _poll_req_data_free);
context =
nm_g_main_context_push_thread_default_if_necessary(nm_http_client_get_main_context(self));
@ -570,28 +577,28 @@ nm_http_client_poll_get(NMHttpClient *self,
nmcs_utils_poll(poll_timeout_ms,
ratelimit_timeout_ms,
0,
_poll_get_probe_start_fcn,
_poll_get_probe_finish_fcn,
poll_get_data,
_poll_req_probe_start_fcn,
_poll_req_probe_finish_fcn,
poll_req_data,
cancellable,
_poll_get_done_cb,
poll_get_data);
_poll_req_done_cb,
poll_req_data);
}
gboolean
nm_http_client_poll_get_finish(NMHttpClient *self,
nm_http_client_poll_req_finish(NMHttpClient *self,
GAsyncResult *result,
long *out_response_code,
GBytes **out_response_data,
GError **error)
{
PollGetData *poll_get_data;
PollReqData *poll_req_data;
GTask *task;
gboolean success;
gs_free_error GError *local_error = NULL;
g_return_val_if_fail(NM_HTTP_CLIENT(self), FALSE);
g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_poll_get), FALSE);
g_return_val_if_fail(nm_g_task_is_valid(result, self, nm_http_client_poll_req), FALSE);
task = G_TASK(result);
@ -606,10 +613,10 @@ nm_http_client_poll_get_finish(NMHttpClient *self,
return FALSE;
}
poll_get_data = g_task_get_task_data(task);
poll_req_data = g_task_get_task_data(task);
NM_SET_OUT(out_response_code, poll_get_data->response_code);
NM_SET_OUT(out_response_data, g_steal_pointer(&poll_get_data->response_data));
NM_SET_OUT(out_response_code, poll_req_data->response_code);
NM_SET_OUT(out_response_data, g_steal_pointer(&poll_req_data->response_data));
return TRUE;
}

View file

@ -28,40 +28,26 @@ GMainContext *nm_http_client_get_main_context(NMHttpClient *self);
/*****************************************************************************/
void nm_http_client_get(NMHttpClient *self,
const char *uri,
int timeout_msec,
gssize max_data,
const char *const *http_headers,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean nm_http_client_get_finish(NMHttpClient *self,
GAsyncResult *result,
long *out_response_code,
GBytes **out_response_data,
GError **error);
typedef gboolean (*NMHttpClientPollGetCheckFcn)(long response_code,
typedef gboolean (*NMHttpClientPollReqCheckFcn)(long response_code,
GBytes *response_data,
gpointer check_user_data,
GError **error);
void nm_http_client_poll_get(NMHttpClient *self,
void nm_http_client_poll_req(NMHttpClient *self,
const char *uri,
int request_timeout_ms,
gssize request_max_data,
int poll_timeout_ms,
int ratelimit_timeout_ms,
const char *const *http_headers,
const char *http_method,
GCancellable *cancellable,
NMHttpClientPollGetCheckFcn check_fcn,
NMHttpClientPollReqCheckFcn check_fcn,
gpointer check_user_data,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean nm_http_client_poll_get_finish(NMHttpClient *self,
gboolean nm_http_client_poll_req_finish(NMHttpClient *self,
GAsyncResult *result,
long *out_response_code,
GBytes **out_response_data,

View file

@ -77,7 +77,7 @@ _detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer us
gs_free_error GError *get_error = NULL;
gs_free_error GError *error = NULL;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
if (nm_utils_error_is_cancelled(get_error)) {
g_task_return_error(task, g_steal_pointer(&get_error));
@ -104,13 +104,14 @@ detect(NMCSProvider *provider, GTask *task)
http_client = nmcs_provider_get_http_client(provider);
nm_http_client_poll_get(http_client,
nm_http_client_poll_req(http_client,
(uri = _aliyun_uri_concat(NM_ALIYUN_API_VERSION "/meta-data/")),
HTTP_TIMEOUT_MS,
256 * 1024,
7000,
1000,
NULL,
NULL,
g_task_get_cancellable(task),
NULL,
NULL,
@ -144,7 +145,7 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
gsize i;
gsize len;
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
nm_http_client_poll_req_finish(http_client, result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -302,7 +303,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
GHashTableIter h_iter;
NMHttpClient *http_client;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -356,7 +357,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
v_mac_data->path);
get_config_data->n_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
http_client,
(uri1 = _aliyun_uri_interfaces(v_mac_data->path,
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
@ -366,6 +367,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
10000,
1000,
NULL,
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -373,7 +375,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
config_iface_data);
get_config_data->n_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
http_client,
(uri2 = _aliyun_uri_interfaces(v_mac_data->path,
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
@ -383,6 +385,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
10000,
1000,
NULL,
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -390,7 +393,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
config_iface_data);
get_config_data->n_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
http_client,
(uri3 = _aliyun_uri_interfaces(v_mac_data->path,
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
@ -400,6 +403,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
10000,
1000,
NULL,
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -407,7 +411,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
config_iface_data);
get_config_data->n_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
http_client,
(uri4 = _aliyun_uri_interfaces(v_mac_data->path,
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
@ -417,6 +421,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
10000,
1000,
NULL,
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -424,7 +429,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
config_iface_data);
get_config_data->n_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
http_client,
(uri5 = _aliyun_uri_interfaces(v_mac_data->path,
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
@ -434,6 +439,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
10000,
1000,
NULL,
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -524,13 +530,14 @@ get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_dat
* MAC addresses, then we poll until we see them. They might not yet be
* around from the start...
*/
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
nm_http_client_poll_req(nmcs_provider_get_http_client(provider),
(uri = _aliyun_uri_interfaces()),
HTTP_TIMEOUT_MS,
256 * 1024,
15000,
1000,
NULL,
NULL,
get_config_data->intern_cancellable,
_get_config_metadata_ready_check,
get_config_data,

View file

@ -42,7 +42,7 @@ _detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer us
gs_free_error GError *get_error = NULL;
gs_free_error GError *error = NULL;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
if (nm_utils_error_is_cancelled(get_error)) {
g_task_return_error(task, g_steal_pointer(&get_error));
@ -69,13 +69,14 @@ detect(NMCSProvider *provider, GTask *task)
http_client = nmcs_provider_get_http_client(provider);
nm_http_client_poll_get(http_client,
nm_http_client_poll_req(http_client,
(uri = _azure_uri_concat("/metadata/instance")),
HTTP_TIMEOUT_MS,
256 * 1024,
7000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
NULL,
g_task_get_cancellable(task),
NULL,
NULL,
@ -121,7 +122,7 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
in_addr_t tmp_addr;
int tmp_prefix = -1;
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
nm_http_client_poll_req_finish(http_client, result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -241,7 +242,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
gsize line_len;
char iface_idx_str[30];
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -283,7 +284,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
iface_data->n_iface_data_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
NM_HTTP_CLIENT(source),
(uri = _azure_uri_interfaces(iface_idx_str,
"/ipv4/ipAddress/",
@ -294,6 +295,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -308,7 +310,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
gs_free char *uri = NULL;
iface_data->n_iface_data_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
NM_HTTP_CLIENT(source),
(uri = _azure_uri_interfaces(iface_idx_str, "/ipv4/subnet/0/address/")),
HTTP_TIMEOUT_MS,
@ -316,6 +318,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -325,7 +328,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
nm_clear_g_free(&uri);
iface_data->n_iface_data_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
NM_HTTP_CLIENT(source),
(uri = _azure_uri_interfaces(iface_idx_str, "/ipv4/subnet/0/prefix/")),
HTTP_TIMEOUT_MS,
@ -333,6 +336,7 @@ _get_config_ips_prefix_list_cb(GObject *source, GAsyncResult *result, gpointer u
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -357,7 +361,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
gs_free const char *uri = NULL;
char buf[100];
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -408,13 +412,14 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/ipv4/ipAddress/", iface_data->intern_iface_idx);
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
nm_http_client_poll_req(NM_HTTP_CLIENT(source),
(uri = _azure_uri_interfaces(buf)),
HTTP_TIMEOUT_MS,
512 * 1024,
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -441,7 +446,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
guint i;
gssize extern_iface_idx_cnt = 0;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -508,13 +513,14 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
nm_sprintf_buf(buf, "%" G_GSSIZE_FORMAT "/macAddress", iface_data->intern_iface_idx);
get_config_data->n_pending++;
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
nm_http_client_poll_req(NM_HTTP_CLIENT(source),
(uri = _azure_uri_interfaces(buf)),
HTTP_TIMEOUT_MS,
512 * 1024,
10000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -531,13 +537,14 @@ get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_dat
{
gs_free const char *uri = NULL;
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
nm_http_client_poll_req(nmcs_provider_get_http_client(provider),
(uri = _azure_uri_interfaces()),
HTTP_TIMEOUT_MS,
256 * 1024,
15000,
1000,
NM_MAKE_STRV(NM_AZURE_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,

View file

@ -16,6 +16,11 @@
#define NM_EC2_METADATA_URL_BASE /* $NM_EC2_BASE/$NM_EC2_API_VERSION */ \
"/meta-data/network/interfaces/macs/"
/* Token TTL of 180 seconds is chosen abitrarily, in hope that it is
* surely more than enough to read all relevant metadata. */
#define NM_EC2_TOKEN_TTL_HEADER "X-aws-ec2-metadata-token-ttl-seconds: 180"
#define NM_EC2_TOKEN_HEADER "X-aws-ec2-metadata-token: "
static const char *
_ec2_base(void)
{
@ -44,8 +49,15 @@ again:
/*****************************************************************************/
enum {
NM_EC2_HTTP_HEADER_TOKEN,
NM_EC2_HTTP_HEADER_SENTINEL,
_NM_EC2_HTTP_HEADER_NUM,
};
struct _NMCSProviderEC2 {
NMCSProvider parent;
char *token;
};
struct _NMCSProviderEC2Class {
@ -56,23 +68,18 @@ G_DEFINE_TYPE(NMCSProviderEC2, nmcs_provider_ec2, NMCS_TYPE_PROVIDER);
/*****************************************************************************/
static gboolean
_detect_get_meta_data_check_cb(long response_code,
GBytes *response,
gpointer check_user_data,
GError **error)
{
return response_code == 200 && nmcs_utils_parse_get_full_line(response, "ami-id");
}
static void
_detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
_detect_get_token_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
gs_unref_object GTask *task = user_data;
NMCSProviderEC2 *self = NMCS_PROVIDER_EC2(g_task_get_source_object(task));
gs_unref_bytes GBytes *response = NULL;
gs_free_error GError *get_error = NULL;
gs_free_error GError *error = NULL;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
nm_clear_g_free(&self->token);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &get_error);
if (nm_utils_error_is_cancelled(get_error)) {
g_task_return_error(task, g_steal_pointer(&get_error));
@ -88,6 +95,12 @@ _detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer us
return;
}
/* We use the token as-is. Special characters can cause confusion (e.g.
* response splitting), but we're not crossing a security boundary.
* None of the examples in AWS documentation does any sort of
* sanitization either. */
self->token = g_strconcat(NM_EC2_TOKEN_HEADER, g_bytes_get_data(response, NULL), NULL);
g_task_return_boolean(task, TRUE);
}
@ -99,17 +112,18 @@ detect(NMCSProvider *provider, GTask *task)
http_client = nmcs_provider_get_http_client(provider);
nm_http_client_poll_get(http_client,
(uri = _ec2_uri_concat("latest/meta-data/")),
nm_http_client_poll_req(http_client,
(uri = _ec2_uri_concat("latest/api/token")),
HTTP_TIMEOUT_MS,
256 * 1024,
7000,
1000,
NULL,
NM_MAKE_STRV(NM_EC2_TOKEN_TTL_HEADER),
"PUT",
g_task_get_cancellable(task),
_detect_get_meta_data_check_cb,
NULL,
_detect_get_meta_data_done_cb,
NULL,
_detect_get_token_done_cb,
task);
}
@ -126,7 +140,7 @@ _get_config_fetch_done_cb(NMHttpClient *http_client,
in_addr_t tmp_addr;
int tmp_prefix;
nm_http_client_poll_get_finish(http_client, result, NULL, &response, &error);
nm_http_client_poll_req_finish(http_client, result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -197,6 +211,7 @@ static void
_get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
NMCSProviderGetConfigTaskData *get_config_data;
NMCSProviderEC2 *self;
gs_unref_hashtable GHashTable *response_parsed = NULL;
gs_free_error GError *error = NULL;
GetConfigMetadataMac *v_mac_data;
@ -204,12 +219,13 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
GHashTableIter h_iter;
NMHttpClient *http_client;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &error);
if (nm_utils_error_is_cancelled(error))
return;
get_config_data = user_data;
self = NMCS_PROVIDER_EC2(get_config_data->self);
response_parsed = g_steal_pointer(&get_config_data->extra_data);
get_config_data->extra_data_destroy = NULL;
@ -254,7 +270,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
v_mac_data->path);
get_config_data->n_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
http_client,
(uri1 = _ec2_uri_interfaces(v_mac_data->path,
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
@ -263,6 +279,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
512 * 1024,
10000,
1000,
NM_MAKE_STRV(self->token),
NULL,
get_config_data->intern_cancellable,
NULL,
@ -271,7 +288,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
config_iface_data);
get_config_data->n_pending++;
nm_http_client_poll_get(
nm_http_client_poll_req(
http_client,
(uri2 = _ec2_uri_interfaces(v_mac_data->path,
NM_STR_HAS_SUFFIX(v_mac_data->path, "/") ? "" : "/",
@ -280,6 +297,7 @@ _get_config_metadata_ready_cb(GObject *source, GAsyncResult *result, gpointer us
512 * 1024,
10000,
1000,
NM_MAKE_STRV(self->token),
NULL,
get_config_data->intern_cancellable,
NULL,
@ -365,18 +383,25 @@ _get_config_metadata_ready_check(long response_code,
static void
get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_data)
{
gs_free char *uri = NULL;
NMCSProviderEC2 *self = NMCS_PROVIDER_EC2(provider);
gs_free char *uri = NULL;
/* This can be called only if detect() succeeded, which implies
* there must be a token.
*/
nm_assert(self->token);
/* 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
* around from the start...
*/
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
nm_http_client_poll_req(nmcs_provider_get_http_client(provider),
(uri = _ec2_uri_interfaces()),
HTTP_TIMEOUT_MS,
256 * 1024,
15000,
1000,
NM_MAKE_STRV(self->token),
NULL,
get_config_data->intern_cancellable,
_get_config_metadata_ready_check,
@ -391,11 +416,24 @@ static void
nmcs_provider_ec2_init(NMCSProviderEC2 *self)
{}
static void
dispose(GObject *object)
{
NMCSProviderEC2 *self = NMCS_PROVIDER_EC2(object);
nm_clear_g_free(&self->token);
G_OBJECT_CLASS(nmcs_provider_ec2_parent_class)->dispose(object);
}
static void
nmcs_provider_ec2_class_init(NMCSProviderEC2Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
NMCSProviderClass *provider_class = NMCS_PROVIDER_CLASS(klass);
object_class->dispose = dispose;
provider_class->_name = "ec2";
provider_class->_env_provider_enabled = NMCS_ENV_VARIABLE("NM_CLOUD_SETUP_EC2");
provider_class->detect = detect;

View file

@ -45,7 +45,7 @@ _detect_get_meta_data_done_cb(GObject *source, GAsyncResult *result, gpointer us
gs_free_error GError *get_error = NULL;
gs_free_error GError *error = NULL;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, NULL, &get_error);
if (nm_utils_error_is_cancelled(get_error)) {
g_task_return_error(task, g_steal_pointer(&get_error));
@ -72,13 +72,14 @@ detect(NMCSProvider *provider, GTask *task)
http_client = nmcs_provider_get_http_client(provider);
nm_http_client_poll_get(http_client,
nm_http_client_poll_req(http_client,
(uri = _gcp_uri_concat("id")),
HTTP_TIMEOUT_MS,
256 * 1024,
7000,
1000,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
NULL,
g_task_get_cancellable(task),
NULL,
NULL,
@ -114,7 +115,7 @@ _get_config_fip_cb(GObject *source, GAsyncResult *result, gpointer user_data)
NMIPRoute **routes_arr;
NMIPRoute *route_new;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -171,7 +172,7 @@ _get_config_ips_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
gsize line_len;
guint i;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -220,13 +221,14 @@ _get_config_ips_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
const char *str = uri_arr->pdata[i];
gs_free const char *uri = NULL;
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
nm_http_client_poll_req(NM_HTTP_CLIENT(source),
(uri = _gcp_uri_interfaces(str)),
HTTP_TIMEOUT_MS,
HTTP_REQ_MAX_DATA,
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -252,7 +254,7 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
NMCSProviderGetConfigTaskData *get_config_data;
gboolean is_requested;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -306,13 +308,14 @@ _get_config_iface_cb(GObject *source, GAsyncResult *result, gpointer user_data)
nm_sprintf_buf(sbuf, "%" G_GSSIZE_FORMAT "/forwarded-ips/", iface_data->intern_iface_idx);
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
nm_http_client_poll_req(NM_HTTP_CLIENT(source),
(uri = _gcp_uri_interfaces(sbuf)),
HTTP_TIMEOUT_MS,
HTTP_REQ_MAX_DATA,
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -339,7 +342,7 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
guint i;
gssize extern_iface_idx_cnt = 0;
nm_http_client_poll_get_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
if (nm_utils_error_is_cancelled(error))
return;
@ -405,13 +408,14 @@ _get_net_ifaces_list_cb(GObject *source, GAsyncResult *result, gpointer user_dat
nm_sprintf_buf(sbuf, "%" G_GSSIZE_FORMAT "/mac", data->intern_iface_idx);
get_config_data->n_pending++;
nm_http_client_poll_get(NM_HTTP_CLIENT(source),
nm_http_client_poll_req(NM_HTTP_CLIENT(source),
(uri = _gcp_uri_interfaces(sbuf)),
HTTP_TIMEOUT_MS,
HTTP_REQ_MAX_DATA,
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,
@ -428,13 +432,14 @@ get_config(NMCSProvider *provider, NMCSProviderGetConfigTaskData *get_config_dat
{
gs_free const char *uri = NULL;
nm_http_client_poll_get(nmcs_provider_get_http_client(provider),
nm_http_client_poll_req(nmcs_provider_get_http_client(provider),
(uri = _gcp_uri_interfaces()),
HTTP_TIMEOUT_MS,
HTTP_REQ_MAX_DATA,
HTTP_POLL_TIMEOUT_MS,
HTTP_RATE_LIMIT_MS,
NM_MAKE_STRV(NM_GCP_METADATA_HEADER),
NULL,
get_config_data->intern_cancellable,
NULL,
NULL,

View file

@ -152,8 +152,36 @@ typedef struct {
const char *_name;
const char *_env_provider_enabled;
/**
* detect:
* @self: the #NMCSProvider
* @task: a #GTask that's completed when the detection finishes.
*
* Checks whether the metadata of a particular cloud provider is
* accessible on the host machine. The check runs asynchronously.
*
* When the check finishes, @task is completed. If the check was
* successful, @task returns a gboolean of %TRUE. Otherwise
* a %FALSE value or an error is returned.
*
* The routine has to be called before the get_config() can be
* used.
*/
void (*detect)(NMCSProvider *self, GTask *task);
/**
* get_config:
* @self: the #NMCSProvider
* @get_config_data: encapsulates a #GTask and network configuration data
*
* Collects the network configuration from metadata service of a
* particular cloud provider. The metadata is traversed and checked
* asynchronously, completing a task encapsulated in @get_config_data
* upon finishing.
*
* Call to detect() with a successful result is necessary before
* using this routine.
*/
void (*get_config)(NMCSProvider *self, NMCSProviderGetConfigTaskData *get_config_data);
} NMCSProviderClass;