
On Thu, Sep 09, 2021 at 09:48:48AM +0100, Daniel P. Berrangé wrote:
On Wed, Sep 08, 2021 at 11:01:17AM -0700, William Douglas wrote:
The virCHMonitorGet function needed to be able to return data from the hypervisor. This functionality is needed in order for the driver to support PTY enablement and getting details about the VM state.
Signed-off-by: William Douglas <william.douglas@intel.com> --- src/ch/ch_monitor.c | 46 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c index b4bc10bfcf..44b99ef07a 100644 --- a/src/ch/ch_monitor.c +++ b/src/ch/ch_monitor.c @@ -611,12 +611,36 @@ virCHMonitorPutNoContent(virCHMonitor *mon, const char *endpoint) return ret; }
+struct curl_data { + char *content; + size_t size; +}; + +static size_t +curl_callback(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t content_size = size * nmemb; + struct curl_data *data = (struct curl_data *)userp;
FWIW, the type cast here is redundant as 'void *' can be directly assigned to/from any other type.
+ + if (content_size == 0) + return content_size; + + data->content = g_realloc(data->content, data->size + content_size); + + memcpy(&(data->content[data->size]), contents, content_size); + data->size += content_size; + + return content_size; +} + static int -virCHMonitorGet(virCHMonitor *mon, const char *endpoint) +virCHMonitorGet(virCHMonitor *mon, const char *endpoint, virJSONValue **response) { g_autofree char *url = NULL; int responseCode = 0; int ret = -1; + struct curl_slist *headers = NULL; + struct curl_data data = {0};
url = g_strdup_printf("%s/%s", URL_ROOT, endpoint);
@@ -628,12 +652,30 @@ virCHMonitorGet(virCHMonitor *mon, const char *endpoint) curl_easy_setopt(mon->handle, CURLOPT_UNIX_SOCKET_PATH, mon->socketpath); curl_easy_setopt(mon->handle, CURLOPT_URL, url);
+ if (response) { + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(mon->handle, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(mon->handle, CURLOPT_WRITEFUNCTION, curl_callback); + curl_easy_setopt(mon->handle, CURLOPT_WRITEDATA, (void *)&data); + } + responseCode = virCHMonitorCurlPerform(mon->handle);
virObjectUnlock(mon);
- if (responseCode == 200 || responseCode == 204) + if (responseCode == 200 || responseCode == 204) { ret = 0; + if (response) { + data.content = g_realloc(data.content, data.size + 1); + data.content[data.size] = 0; + *response = virJSONValueFromString(data.content);
Oh, well need to add:
if (!*response) return -1;
in case JSON parsing fails
Actually slight more to avoid a leak. @@ -665,14 +665,17 @@ virCHMonitorGet(virCHMonitor *mon, const char *endpoint, virJSONValue **response virObjectUnlock(mon); if (responseCode == 200 || responseCode == 204) { - ret = 0; if (response) { data.content = g_realloc(data.content, data.size + 1); data.content[data.size] = 0; *response = virJSONValueFromString(data.content); + if (!*response) + goto cleanup; } + ret = 0; } + cleanup: g_free(data.content); /* reset the libcurl handle to avoid leaking a stack pointer to data */ curl_easy_reset(mon->handle); Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|