diff options
| author | Michael Roth <mdroth@linux.vnet.ibm.com> | 2012-02-07 13:56:48 -0600 |
|---|---|---|
| committer | Michael Roth <mdroth@linux.vnet.ibm.com> | 2012-03-12 15:09:23 -0500 |
| commit | 3cf0bed8369267184e5dc5b58882811519d67437 (patch) | |
| tree | a9c32d61d08ec7ab795b1b2cc4d74252087e1130 /qemu-ga.c | |
| parent | 3424fc9f16a1e7d1c48eb6d605eb0ca63e199ec2 (diff) | |
| download | focaccia-qemu-3cf0bed8369267184e5dc5b58882811519d67437.tar.gz focaccia-qemu-3cf0bed8369267184e5dc5b58882811519d67437.zip | |
qemu-ga: add guest-sync-delimited
guest-sync leaves it as an exercise to the user as to how to reliably obtain the response to guest-sync if the client had previously read in a partial response (due qemu-ga previously being restarted mid-"sentence" due to reboot, forced restart, etc). qemu-ga handles this situation on its end by having a client precede their guest-sync request with a 0xFF byte (invalid UTF-8), which qemu-ga/QEMU JSON parsers will treat as a flush event. Thus we can reliably flush the qemu-ga parser state in preparation for receiving the guest-sync request. guest-sync-delimited provides the same functionality for a client: when a guest-sync-delimited is issued, qemu-ga will precede it's response with a 0xFF byte that the client can use as an indicator to flush its buffer/parser state in preparation for reliably receiving the guest-sync-delimited response. It is also useful as an optimization for clients, since, after issuing a guest-sync-delimited, clients can safely discard all stale data read from the channel until the 0xFF is found. More information available on the wiki: http://wiki.qemu.org/Features/QAPI/GuestAgent#QEMU_Guest_Agent_Protocol Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Diffstat (limited to 'qemu-ga.c')
| -rw-r--r-- | qemu-ga.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/qemu-ga.c b/qemu-ga.c index 1c90e6ef0d..d6f786e50d 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -41,6 +41,7 @@ #define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0" #endif #define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid" +#define QGA_SENTINEL_BYTE 0xFF struct GAState { JSONMessageParser parser; @@ -54,9 +55,10 @@ struct GAState { #ifdef _WIN32 GAService service; #endif + bool delimit_response; }; -static struct GAState *ga_state; +struct GAState *ga_state; #ifdef _WIN32 DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, @@ -198,6 +200,11 @@ static void ga_log(const gchar *domain, GLogLevelFlags level, } } +void ga_set_response_delimited(GAState *s) +{ + s->delimit_response = true; +} + #ifndef _WIN32 static void become_daemon(const char *pidfile) { @@ -254,7 +261,7 @@ fail: static int send_response(GAState *s, QObject *payload) { const char *buf; - QString *payload_qstr; + QString *payload_qstr, *response_qstr; GIOStatus status; g_assert(payload && s->channel); @@ -264,10 +271,20 @@ static int send_response(GAState *s, QObject *payload) return -EINVAL; } - qstring_append_chr(payload_qstr, '\n'); - buf = qstring_get_str(payload_qstr); + if (s->delimit_response) { + s->delimit_response = false; + response_qstr = qstring_new(); + qstring_append_chr(response_qstr, QGA_SENTINEL_BYTE); + qstring_append(response_qstr, qstring_get_str(payload_qstr)); + QDECREF(payload_qstr); + } else { + response_qstr = payload_qstr; + } + + qstring_append_chr(response_qstr, '\n'); + buf = qstring_get_str(response_qstr); status = ga_channel_write_all(s->channel, buf, strlen(buf)); - QDECREF(payload_qstr); + QDECREF(response_qstr); if (status != G_IO_STATUS_NORMAL) { return -EIO; } |