On Thu, Aug 26, 2021 at 02:59:17PM -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@xxxxxxxxx> > --- > src/ch/ch_monitor.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 42 insertions(+), 2 deletions(-) > > diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c > index b4bc10bfcf..ee7e4683e3 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; > + > + 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,28 @@ 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); This bit feels dodgy to me. mon->handle has its lifetime tied to the virCHMonitor object, but '&data' is allocated on the stack. IOW, this pointer is persistent, but it goes out of scope. I guess you're relying on the fact that calls to this method are serialized, and we re-write the bad pointer on every call, but if 'response' is NULL on the next call we're not going to do that re-write. Can all these options be set unconditionally when the mon->handle is first created ? > + } > + > 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); > + } > + } > + > + g_free(data.content); > > return ret; > } 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 :|