summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--QMP/qmp-events.txt64
-rw-r--r--monitor.c10
-rw-r--r--monitor.h3
-rw-r--r--ui/spice-core.c75
4 files changed, 152 insertions, 0 deletions
diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index aa2021082f..0ce5d4efe2 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -182,6 +182,70 @@ Example:
"host": "127.0.0.1", "sasl_username": "luiz" } },
"timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
+SPICE_CONNECTED, SPICE_DISCONNECTED
+-----------------------------------
+
+Emitted when a SPICE client connects or disconnects.
+
+Data:
+
+- "server": Server information (json-object)
+ - "host": IP address (json-string)
+ - "port": port number (json-string)
+ - "family": address family (json-string, "ipv4" or "ipv6")
+- "client": Client information (json-object)
+ - "host": IP address (json-string)
+ - "port": port number (json-string)
+ - "family": address family (json-string, "ipv4" or "ipv6")
+
+Example:
+
+{ "timestamp": {"seconds": 1290688046, "microseconds": 388707},
+ "event": "SPICE_CONNECTED",
+ "data": {
+ "server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
+ "client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
+}}
+
+
+SPICE_INITIALIZED
+-----------------
+
+Emitted after initial handshake and authentication takes place (if any)
+and the SPICE channel is up'n'running
+
+Data:
+
+- "server": Server information (json-object)
+ - "host": IP address (json-string)
+ - "port": port number (json-string)
+ - "family": address family (json-string, "ipv4" or "ipv6")
+ - "auth": authentication method (json-string, optional)
+- "client": Client information (json-object)
+ - "host": IP address (json-string)
+ - "port": port number (json-string)
+ - "family": address family (json-string, "ipv4" or "ipv6")
+ - "connection-id": spice connection id. All channels with the same id
+ belong to the same spice session (json-int)
+ - "channel-type": channel type. "1" is the main control channel, filter for
+ this one if you want track spice sessions only (json-int)
+ - "channel-id": channel id. Usually "0", might be different needed when
+ multiple channels of the same type exist, such as multiple
+ display channels in a multihead setup (json-int)
+ - "tls": whevener the channel is encrypted (json-bool)
+
+Example:
+
+{ "timestamp": {"seconds": 1290688046, "microseconds": 417172},
+ "event": "SPICE_INITIALIZED",
+ "data": {"server": {"auth": "spice", "port": "5921",
+ "family": "ipv4", "host": "127.0.0.1"},
+ "client": {"port": "49004", "family": "ipv4", "channel-type": 3,
+ "connection-id": 1804289383, "host": "127.0.0.1",
+ "channel-id": 0, "tls": true}
+}}
+
+
WATCHDOG
--------
diff --git a/monitor.c b/monitor.c
index ec31eac8c1..f04dda527a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -59,6 +59,7 @@
#ifdef CONFIG_SIMPLE_TRACE
#include "trace.h"
#endif
+#include "ui/qemu-spice.h"
//#define DEBUG
//#define DEBUG_COMPLETION
@@ -459,6 +460,15 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
case QEVENT_WATCHDOG:
event_name = "WATCHDOG";
break;
+ case QEVENT_SPICE_CONNECTED:
+ event_name = "SPICE_CONNECTED";
+ break;
+ case QEVENT_SPICE_INITIALIZED:
+ event_name = "SPICE_INITIALIZED";
+ break;
+ case QEVENT_SPICE_DISCONNECTED:
+ event_name = "SPICE_DISCONNECTED";
+ break;
default:
abort();
break;
diff --git a/monitor.h b/monitor.h
index 2d36bba87f..4f2d328db5 100644
--- a/monitor.h
+++ b/monitor.h
@@ -32,6 +32,9 @@ typedef enum MonitorEvent {
QEVENT_BLOCK_IO_ERROR,
QEVENT_RTC_CHANGE,
QEVENT_WATCHDOG,
+ QEVENT_SPICE_CONNECTED,
+ QEVENT_SPICE_INITIALIZED,
+ QEVENT_SPICE_DISCONNECTED,
QEVENT_MAX,
} MonitorEvent;
diff --git a/ui/spice-core.c b/ui/spice-core.c
index b7fa0315bd..93461c6d06 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -18,16 +18,24 @@
#include <spice.h>
#include <spice-experimental.h>
+#include <netdb.h>
+
#include "qemu-common.h"
#include "qemu-spice.h"
#include "qemu-timer.h"
#include "qemu-queue.h"
#include "qemu-x509.h"
+#include "qemu_socket.h"
+#include "qint.h"
+#include "qbool.h"
+#include "qstring.h"
+#include "qjson.h"
#include "monitor.h"
/* core bits */
static SpiceServer *spice_server;
+static const char *auth = "spice";
int using_spice = 0;
struct SpiceTimer {
@@ -121,6 +129,68 @@ static void watch_remove(SpiceWatch *watch)
qemu_free(watch);
}
+#if SPICE_INTERFACE_CORE_MINOR >= 3
+
+static void add_addr_info(QDict *dict, struct sockaddr *addr, int len)
+{
+ char host[NI_MAXHOST], port[NI_MAXSERV];
+ const char *family;
+
+ getnameinfo(addr, len, host, sizeof(host), port, sizeof(port),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ family = inet_strfamily(addr->sa_family);
+
+ qdict_put(dict, "host", qstring_from_str(host));
+ qdict_put(dict, "port", qstring_from_str(port));
+ qdict_put(dict, "family", qstring_from_str(family));
+}
+
+static void add_channel_info(QDict *dict, SpiceChannelEventInfo *info)
+{
+ int tls = info->flags & SPICE_CHANNEL_EVENT_FLAG_TLS;
+
+ qdict_put(dict, "connection-id", qint_from_int(info->connection_id));
+ qdict_put(dict, "channel-type", qint_from_int(info->type));
+ qdict_put(dict, "channel-id", qint_from_int(info->id));
+ qdict_put(dict, "tls", qbool_from_int(tls));
+}
+
+static void channel_event(int event, SpiceChannelEventInfo *info)
+{
+ static const int qevent[] = {
+ [ SPICE_CHANNEL_EVENT_CONNECTED ] = QEVENT_SPICE_CONNECTED,
+ [ SPICE_CHANNEL_EVENT_INITIALIZED ] = QEVENT_SPICE_INITIALIZED,
+ [ SPICE_CHANNEL_EVENT_DISCONNECTED ] = QEVENT_SPICE_DISCONNECTED,
+ };
+ QDict *server, *client;
+ QObject *data;
+
+ client = qdict_new();
+ add_addr_info(client, &info->paddr, info->plen);
+
+ server = qdict_new();
+ add_addr_info(server, &info->laddr, info->llen);
+
+ if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
+ qdict_put(server, "auth", qstring_from_str(auth));
+ add_channel_info(client, info);
+ }
+
+ data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
+ QOBJECT(client), QOBJECT(server));
+ monitor_protocol_event(qevent[event], data);
+ qobject_decref(data);
+}
+
+#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
+
+static QList *channel_list_get(void)
+{
+ return NULL;
+}
+
+#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */
+
static SpiceCoreInterface core_interface = {
.base.type = SPICE_INTERFACE_CORE,
.base.description = "qemu core services",
@@ -135,6 +205,10 @@ static SpiceCoreInterface core_interface = {
.watch_add = watch_add,
.watch_update_mask = watch_update_mask,
.watch_remove = watch_remove,
+
+#if SPICE_INTERFACE_CORE_MINOR >= 3
+ .channel_event = channel_event,
+#endif
};
/* config string parsing */
@@ -316,6 +390,7 @@ void qemu_spice_init(void)
spice_server_set_ticket(spice_server, password, 0, 0, 0);
}
if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
+ auth = "none";
spice_server_set_noauth(spice_server);
}