}
+static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject,
+ void *opaque)
+{
+ struct qemud_client *client = opaque;
+ remote_domain_event_graphics_msg data;
+ int i;
+
+ if (!client)
+ return -1;
+
+ REMOTE_DEBUG("Relaying domain graphics event %s %d %d - %d %s %s - %d %s %s - %s", dom->name, dom->id, phase,
+ local->family, local->service, local->node,
+ remote->family, remote->service, remote->node,
+ authScheme);
+
+ REMOTE_DEBUG("Subject %d", subject->nidentity);
+ for (i = 0 ; i < subject->nidentity ; i++) {
+ REMOTE_DEBUG(" %s=%s", subject->identities[i].type, subject->identities[i].name);
+ }
+
+ virMutexLock(&client->lock);
+
+ /* build return data */
+ memset(&data, 0, sizeof data);
+ make_nonnull_domain (&data.dom, dom);
+ data.phase = phase;
+ data.authScheme = (char*)authScheme;
+
+ data.local.family = local->family;
+ data.local.node = (char *)local->node;
+ data.local.service = (char *)local->service;
+
+ data.remote.family = remote->family;
+ data.remote.node = (char*)remote->node;
+ data.remote.service = (char*)remote->service;
+
+ data.subject.subject_len = subject->nidentity;
+ if (VIR_ALLOC_N(data.subject.subject_val, data.subject.subject_len) < 0) {
+ VIR_WARN0("cannot allocate memory for graphics event subject");
+ return -1;
+ }
+ for (i = 0 ; i < data.subject.subject_len ; i++) {
+ data.subject.subject_val[i].type = (char*)subject->identities[i].type;
+ data.subject.subject_val[i].name = (char*)subject->identities[i].name;
+ }
+
+ remoteDispatchDomainEventSend (client,
+ REMOTE_PROC_DOMAIN_EVENT_GRAPHICS,
+ (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data);
+
+ VIR_FREE(data.subject.subject_val);
+
+ virMutexUnlock(&client->lock);
+
+ return 0;
+}
+
+
static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventRTCChange),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog),
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
+ VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
};
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
.args_filter = (xdrproc_t) xdr_void,
.ret_filter = (xdrproc_t) xdr_void,
},
+{ /* Async event DomainEventGraphics => 171 */
+ .fn = NULL,
+ .args_filter = (xdrproc_t) xdr_void,
+ .ret_filter = (xdrproc_t) xdr_void,
+},
return 0;
}
+static int myDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virDomainPtr dom,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ int i;
+ printf("%s EVENT: Domain %s(%d) graphics ", __func__, virDomainGetName(dom),
+ virDomainGetID(dom));
+
+ switch (phase) {
+ case VIR_DOMAIN_EVENT_GRAPHICS_CONNECT:
+ printf("connected ");
+ break;
+ case VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE:
+ printf("initialized ");
+ break;
+ case VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT:
+ printf("disconnected ");
+ break;
+ }
+
+ printf("local: family=%d node=%s service=%s ",
+ local->family, local->node, local->service);
+ printf("remote: family=%d node=%s service=%s ",
+ remote->family, remote->node, remote->service);
+
+ printf("auth: %s ", authScheme);
+ for (i = 0 ; i < subject->nidentity ; i++) {
+ printf(" identity: %s=%s",
+ subject->identities[i].type,
+ subject->identities[i].name);
+ }
+ printf("\n");
+
+ return 0;
+}
+
static void myFreeFunc(void *opaque)
{
char *str = opaque;
int callback4ret = -1;
int callback5ret = -1;
int callback6ret = -1;
+ int callback7ret = -1;
struct sigaction action_stop = {
.sa_handler = stop
VIR_DOMAIN_EVENT_ID_IO_ERROR,
VIR_DOMAIN_EVENT_CALLBACK(myDomainEventIOErrorCallback),
strdup("callback io error"), myFreeFunc);
+ callback7ret = virConnectDomainEventRegisterAny(dconn,
+ NULL,
+ VIR_DOMAIN_EVENT_ID_GRAPHICS,
+ VIR_DOMAIN_EVENT_CALLBACK(myDomainEventGraphicsCallback),
+ strdup("callback graphics"), myFreeFunc);
if ((callback1ret != -1) &&
(callback2ret != -1) &&
(callback3ret != -1) &&
(callback4ret != -1) &&
(callback5ret != -1) &&
- (callback6ret != -1)) {
+ (callback6ret != -1) &&
+ (callback7ret != -1)) {
while(run) {
struct pollfd pfd = { .fd = h_fd,
.events = h_event,
virConnectDomainEventDeregisterAny(dconn, callback4ret);
virConnectDomainEventDeregisterAny(dconn, callback5ret);
virConnectDomainEventDeregisterAny(dconn, callback6ret);
+ virConnectDomainEventDeregisterAny(dconn, callback7ret);
}
DEBUG0("Closing connection");
int action,
void *opaque);
+/**
+ * virDomainEventGraphicsPhase:
+ *
+ * The phase of the graphics client connection
+ */
+typedef enum {
+ VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0, /* Initial socket connection established */
+ VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE, /* Authentication & setup completed */
+ VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT, /* Final socket disconnection */
+} virDomainEventGraphicsPhase;
+
+/**
+ * virDomainEventGraphicsAddressType:
+ *
+ * The type of address for the connection
+ */
+typedef enum {
+ VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4, /* IPv4 address */
+ VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6, /* IPv6 address */
+} virDomainEventGraphicsAddressType;
+
+
+/**
+ * virDomainEventGraphicsAddress:
+ *
+ * The data structure containing connection address details
+ *
+ */
+struct _virDomainEventGraphicsAddress {
+ int family; /* Address family, virDomainEventGraphicsAddressType */
+ const char *node; /* Address of node (eg IP address) */
+ const char *service; /* Service name/number (eg TCP port) */
+};
+typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
+typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
+
+
+/**
+ * virDomainEventGraphicsSubjectIdentity:
+ *
+ * The data structure representing a single identity
+ *
+ * The types of identity differ according to the authentication scheme,
+ * some examples are 'x509dname' and 'saslUsername'.
+ */
+struct _virDomainEventGraphicsSubjectIdentity {
+ const char *type; /* Type of identity */
+ const char *name; /* Identity value */
+};
+typedef struct _virDomainEventGraphicsSubjectIdentity virDomainEventGraphicsSubjectIdentity;
+typedef virDomainEventGraphicsSubjectIdentity *virDomainEventGraphicsSubjectIdentityPtr;
+
+
+/**
+ * virDomainEventGraphicsSubject:
+ *
+ * The data structure representing an authenticated subject
+ *
+ * A subject will have zero or more identities. The types of
+ * identity differ according to the authentication scheme
+ */
+struct _virDomainEventGraphicsSubject {
+ int nidentity; /* Number of identities in array*/
+ virDomainEventGraphicsSubjectIdentityPtr identities; /* Array of identities for subject */
+};
+typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
+typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
+
+
+/**
+ * virConnectDomainEventGraphicsCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @phase: the phase of the connection
+ * @local: the local server address
+ * @remote: the remote client address
+ * @authScheme: the authentication scheme activated
+ * @subject: the authenticated subject (user)
+ * @opaque: application specified data
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_GRAPHICS with virConnectDomainEventRegisterAny()
+ */
+typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
+ virDomainPtr dom,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject,
+ void *opaque);
+
/**
* VIR_DOMAIN_EVENT_CALLBACK:
*
VIR_DOMAIN_EVENT_ID_RTC_CHANGE = 2, /* virConnectDomainEventRTCChangeCallback */
VIR_DOMAIN_EVENT_ID_WATCHDOG = 3, /* virConnectDomainEventWatchdogCallback */
VIR_DOMAIN_EVENT_ID_IO_ERROR = 4, /* virConnectDomainEventIOErrorCallback */
+ VIR_DOMAIN_EVENT_ID_GRAPHICS = 5, /* virConnectDomainEventGraphicsCallback */
/*
* NB: this enum value will increase over time as new events are
'virConnectDomainEventRTCChangeCallback': "No function types in python",
'virConnectDomainEventWatchdogCallback': "No function types in python",
'virConnectDomainEventIOErrorCallback': "No function types in python",
+ 'virConnectDomainEventGraphicsCallback': "No function types in python",
'virEventAddHandleFunc': "No function types in python",
}
char *devAlias;
int action;
} ioError;
+ struct {
+ int phase;
+ virDomainEventGraphicsAddressPtr local;
+ virDomainEventGraphicsAddressPtr remote;
+ char *authScheme;
+ virDomainEventGraphicsSubjectPtr subject;
+ } graphics;
} data;
};
if (!event)
return;
- if (event->eventID == VIR_DOMAIN_EVENT_ID_IO_ERROR) {
+ switch (event->eventID) {
+ case VIR_DOMAIN_EVENT_ID_IO_ERROR:
VIR_FREE(event->data.ioError.srcPath);
VIR_FREE(event->data.ioError.devAlias);
+ break;
+
+ case VIR_DOMAIN_EVENT_ID_GRAPHICS:
+ if (event->data.graphics.local) {
+ VIR_FREE(event->data.graphics.local->node);
+ VIR_FREE(event->data.graphics.local->service);
+ VIR_FREE(event->data.graphics.local);
+ }
+ if (event->data.graphics.remote) {
+ VIR_FREE(event->data.graphics.remote->node);
+ VIR_FREE(event->data.graphics.remote->service);
+ VIR_FREE(event->data.graphics.remote);
+ }
+ VIR_FREE(event->data.graphics.authScheme);
+ if (event->data.graphics.subject) {
+ int i;
+ for (i = 0 ; i < event->data.graphics.subject->nidentity ; i++) {
+ VIR_FREE(event->data.graphics.subject->identities[i].type);
+ VIR_FREE(event->data.graphics.subject->identities[i].name);
+ }
+ VIR_FREE(event->data.graphics.subject);
+ }
}
VIR_FREE(event->dom.name);
return ev;
}
+
+virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject)
+{
+ virDomainEventPtr ev =
+ virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS,
+ dom->id, dom->name, dom->uuid);
+
+ if (ev) {
+ ev->data.graphics.phase = phase;
+ if (!(ev->data.graphics.authScheme = strdup(authScheme))) {
+ virDomainEventFree(ev);
+ ev = NULL;
+ }
+ ev->data.graphics.local = local;
+ ev->data.graphics.remote = remote;
+ ev->data.graphics.subject = subject;
+ }
+
+ return ev;
+}
+
+virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject)
+{
+ virDomainEventPtr ev =
+ virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_GRAPHICS,
+ obj->def->id, obj->def->name, obj->def->uuid);
+
+ if (ev) {
+ ev->data.graphics.phase = phase;
+ if (!(ev->data.graphics.authScheme = strdup(authScheme))) {
+ virDomainEventFree(ev);
+ ev = NULL;
+ }
+ ev->data.graphics.local = local;
+ ev->data.graphics.remote = remote;
+ ev->data.graphics.subject = subject;
+ }
+
+ return ev;
+}
+
+
/**
* virDomainEventQueueFree:
* @queue: pointer to the queue
cbopaque);
break;
+ case VIR_DOMAIN_EVENT_ID_GRAPHICS:
+ ((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
+ event->data.graphics.phase,
+ event->data.graphics.local,
+ event->data.graphics.remote,
+ event->data.graphics.authScheme,
+ event->data.graphics.subject,
+ cbopaque);
+ break;
+
default:
VIR_WARN("Unexpected event ID %d", event->eventID);
break;
const char *devAlias,
int action);
+virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject);
+virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj,
+ int phase,
+ virDomainEventGraphicsAddressPtr local,
+ virDomainEventGraphicsAddressPtr remote,
+ const char *authScheme,
+ virDomainEventGraphicsSubjectPtr subject);
+
+
+
int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue,
virDomainEventPtr event);
virDomainEventWatchdogNewFromObj;
virDomainEventIOErrorNewFromDom;
virDomainEventIOErrorNewFromObj;
+virDomainEventGraphicsNewFromDom;
+virDomainEventGraphicsNewFromObj;
virDomainEventFree;
virDomainEventDispatchDefaultFunc;
virDomainEventDispatch;
}
+static int
+qemuHandleDomainGraphics(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ int phase,
+ int localFamily,
+ const char *localNode,
+ const char *localService,
+ int remoteFamily,
+ const char *remoteNode,
+ const char *remoteService,
+ const char *authScheme,
+ const char *x509dname,
+ const char *saslUsername)
+{
+ struct qemud_driver *driver = qemu_driver;
+ virDomainEventPtr event;
+ virDomainEventGraphicsAddressPtr localAddr = NULL;
+ virDomainEventGraphicsAddressPtr remoteAddr = NULL;
+ virDomainEventGraphicsSubjectPtr subject = NULL;
+ int i;
+
+ virDomainObjLock(vm);
+
+ if (VIR_ALLOC(localAddr) < 0)
+ goto no_memory;
+ localAddr->family = localFamily;
+ if (!(localAddr->service = strdup(localService)) ||
+ !(localAddr->node = strdup(localNode)))
+ goto no_memory;
+
+ if (VIR_ALLOC(remoteAddr) < 0)
+ goto no_memory;
+ remoteAddr->family = remoteFamily;
+ if (!(remoteAddr->service = strdup(remoteService)) ||
+ !(remoteAddr->node = strdup(remoteNode)))
+ goto no_memory;
+
+ if (VIR_ALLOC(subject) < 0)
+ goto no_memory;
+ if (x509dname) {
+ if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0)
+ goto no_memory;
+ if (!(subject->identities[subject->nidentity].type = strdup("x509dname")) ||
+ !(subject->identities[subject->nidentity].name = strdup(x509dname)))
+ goto no_memory;
+ subject->nidentity++;
+ }
+ if (saslUsername) {
+ if (VIR_REALLOC_N(subject->identities, subject->nidentity+1) < 0)
+ goto no_memory;
+ if (!(subject->identities[subject->nidentity].type = strdup("saslUsername")) ||
+ !(subject->identities[subject->nidentity].name = strdup(saslUsername)))
+ goto no_memory;
+ subject->nidentity++;
+ }
+
+ event = virDomainEventGraphicsNewFromObj(vm, phase, localAddr, remoteAddr, authScheme, subject);
+ virDomainObjUnlock(vm);
+
+ if (event) {
+ qemuDriverLock(driver);
+ qemuDomainEventQueue(driver, event);
+ qemuDriverUnlock(driver);
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+ if (localAddr) {
+ VIR_FREE(localAddr->service);
+ VIR_FREE(localAddr->node);
+ VIR_FREE(localAddr);
+ }
+ if (remoteAddr) {
+ VIR_FREE(remoteAddr->service);
+ VIR_FREE(remoteAddr->node);
+ VIR_FREE(remoteAddr);
+ }
+ if (subject) {
+ for (i = 0 ; i < subject->nidentity ; i++) {
+ VIR_FREE(subject->identities[i].type);
+ VIR_FREE(subject->identities[i].name);
+ }
+ VIR_FREE(subject->identities);
+ VIR_FREE(subject);
+ }
+
+ return -1;
+}
+
+
static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuHandleMonitorEOF,
.diskSecretLookup = findVolumeQcowPassphrase,
.domainRTCChange = qemuHandleDomainRTCChange,
.domainWatchdog = qemuHandleDomainWatchdog,
.domainIOError = qemuHandleDomainIOError,
+ .domainGraphics = qemuHandleDomainGraphics,
};
static int
}
+int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
+ int phase,
+ int localFamily,
+ const char *localNode,
+ const char *localService,
+ int remoteFamily,
+ const char *remoteNode,
+ const char *remoteService,
+ const char *authScheme,
+ const char *x509dname,
+ const char *saslUsername)
+{
+ int ret = -1;
+ VIR_DEBUG("mon=%p", mon);
+
+ qemuMonitorRef(mon);
+ qemuMonitorUnlock(mon);
+ if (mon->cb && mon->cb->domainGraphics)
+ ret = mon->cb->domainGraphics(mon, mon->vm,
+ phase,
+ localFamily, localNode, localService,
+ remoteFamily, remoteNode, remoteService,
+ authScheme, x509dname, saslUsername);
+ qemuMonitorLock(mon);
+ qemuMonitorUnref(mon);
+ return ret;
+}
+
+
+
int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
{
int ret;
virDomainObjPtr vm,
const char *diskAlias,
int action);
+ int (*domainGraphics)(qemuMonitorPtr mon,
+ virDomainObjPtr vm,
+ int phase,
+ int localFamily,
+ const char *localNode,
+ const char *localService,
+ int remoteFamily,
+ const char *remoteNode,
+ const char *remoteService,
+ const char *authScheme,
+ const char *x509dname,
+ const char *saslUsername);
};
int qemuMonitorEmitIOError(qemuMonitorPtr mon,
const char *diskAlias,
int action);
+int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
+ int phase,
+ int localFamily,
+ const char *localNode,
+ const char *localService,
+ int remoteFamily,
+ const char *remoteNode,
+ const char *remoteService,
+ const char *authScheme,
+ const char *x509dname,
+ const char *saslUsername);
+
int qemuMonitorStartCPUs(qemuMonitorPtr mon,
virConnectPtr conn);
static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data);
struct {
const char *type;
{ "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, },
{ "WATCHDOG", qemuMonitorJSONHandleWatchdog, },
{ "DISK_IO_ERROR", qemuMonitorJSONHandleIOError, },
+ { "VNC_CONNECTED", qemuMonitorJSONHandleVNCConnect, },
+ { "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, },
+ { "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, },
};
}
+VIR_ENUM_DECL(qemuMonitorGraphicsAddressFamily)
+VIR_ENUM_IMPL(qemuMonitorGraphicsAddressFamily, VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6 + 1,
+ "ipv4", "ipv6");
+
+static void qemuMonitorJSONHandleVNC(qemuMonitorPtr mon, virJSONValuePtr data, int phase)
+{
+ const char *localNode, *localService, *localFamily;
+ const char *remoteNode, *remoteService, *remoteFamily;
+ const char *authScheme, *saslUsername, *x509dname;
+ int localFamilyID, remoteFamilyID;
+ virJSONValuePtr client;
+ virJSONValuePtr server;
+
+ if (!(client = virJSONValueObjectGet(data, "client"))) {
+ VIR_WARN0("missing client info in VNC event");
+ return;
+ }
+ if (!(server = virJSONValueObjectGet(data, "server"))) {
+ VIR_WARN0("missing server info in VNC event");
+ return;
+ }
+
+ authScheme = virJSONValueObjectGetString(server, "auth");
+
+ localFamily = virJSONValueObjectGetString(server, "family");
+ localNode = virJSONValueObjectGetString(server, "host");
+ localService = virJSONValueObjectGetString(server, "service");
+
+ remoteFamily = virJSONValueObjectGetString(client, "family");
+ remoteNode = virJSONValueObjectGetString(client, "host");
+ remoteService = virJSONValueObjectGetString(client, "service");
+
+ saslUsername = virJSONValueObjectGetString(client, "sasl_username");
+ x509dname = virJSONValueObjectGetString(client, "x509_dname");
+
+ if ((localFamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(localFamily)) < 0) {
+ VIR_WARN("unknown address family '%s'", localFamily);
+ localFamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
+ }
+ if ((remoteFamilyID = qemuMonitorGraphicsAddressFamilyTypeFromString(remoteFamily)) < 0) {
+ VIR_WARN("unknown address family '%s'", remoteFamily);
+ remoteFamilyID = VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4;
+ }
+
+ qemuMonitorEmitGraphics(mon, phase,
+ localFamilyID, localNode, localService,
+ remoteFamilyID, remoteNode, remoteService,
+ authScheme, x509dname, saslUsername);
+}
+
+static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data)
+{
+ qemuMonitorJSONHandleVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT);
+}
+
+
+static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data)
+{
+ qemuMonitorJSONHandleVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE);
+}
+
+
+static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data)
+{
+ qemuMonitorJSONHandleVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
+}
+
+
int
qemuMonitorJSONSetCapabilities(qemuMonitorPtr mon)
{
}
+static virDomainEventPtr
+remoteDomainReadEventGraphics(virConnectPtr conn, XDR *xdr)
+{
+ remote_domain_event_graphics_msg msg;
+ virDomainPtr dom;
+ virDomainEventPtr event = NULL;
+ virDomainEventGraphicsAddressPtr localAddr = NULL;
+ virDomainEventGraphicsAddressPtr remoteAddr = NULL;
+ virDomainEventGraphicsSubjectPtr subject = NULL;
+ int i;
+
+ memset (&msg, 0, sizeof msg);
+
+ /* unmarshall parameters, and process it*/
+ if (! xdr_remote_domain_event_graphics_msg(xdr, &msg) ) {
+ error (conn, VIR_ERR_RPC,
+ _("unable to demarshall reboot event"));
+ return NULL;
+ }
+
+ dom = get_nonnull_domain(conn,msg.dom);
+ if (!dom)
+ return NULL;
+
+ if (VIR_ALLOC(localAddr) < 0)
+ goto no_memory;
+ localAddr->family = msg.local.family;
+ if (!(localAddr->service = strdup(msg.local.service)) ||
+ !(localAddr->node = strdup(msg.local.node)))
+ goto no_memory;
+
+ if (VIR_ALLOC(remoteAddr) < 0)
+ goto no_memory;
+ remoteAddr->family = msg.remote.family;
+ if (!(remoteAddr->service = strdup(msg.remote.service)) ||
+ !(remoteAddr->node = strdup(msg.remote.node)))
+ goto no_memory;
+
+ fprintf(stderr, "Got %d\n", msg.subject.subject_len);
+ if (VIR_ALLOC(subject) < 0)
+ goto no_memory;
+ if (VIR_ALLOC_N(subject->identities, msg.subject.subject_len) < 0)
+ goto no_memory;
+ subject->nidentity = msg.subject.subject_len;
+ for (i = 0 ; i < subject->nidentity ; i++) {
+ fprintf(stderr, " %s=%s\n", msg.subject.subject_val[i].type,
+ msg.subject.subject_val[i].name);
+ if (!(subject->identities[i].type = strdup(msg.subject.subject_val[i].type)) ||
+ !(subject->identities[i].name = strdup(msg.subject.subject_val[i].name)))
+ goto no_memory;
+ }
+
+ event = virDomainEventGraphicsNewFromDom(dom,
+ msg.phase,
+ localAddr,
+ remoteAddr,
+ msg.authScheme,
+ subject);
+ xdr_free ((xdrproc_t) &xdr_remote_domain_event_graphics_msg, (char *) &msg);
+
+ virDomainFree(dom);
+ return event;
+
+no_memory:
+ xdr_free ((xdrproc_t) &xdr_remote_domain_event_graphics_msg, (char *) &msg);
+
+ if (localAddr) {
+ VIR_FREE(localAddr->service);
+ VIR_FREE(localAddr->node);
+ VIR_FREE(localAddr);
+ }
+ if (remoteAddr) {
+ VIR_FREE(remoteAddr->service);
+ VIR_FREE(remoteAddr->node);
+ VIR_FREE(remoteAddr);
+ }
+ if (subject) {
+ for (i = 0 ; i < subject->nidentity ; i++) {
+ VIR_FREE(subject->identities[i].type);
+ VIR_FREE(subject->identities[i].name);
+ }
+ VIR_FREE(subject->identities);
+ VIR_FREE(subject);
+ }
+ return NULL;
+}
+
+
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
remoteSecretOpen (virConnectPtr conn,
virConnectAuthPtr auth,
event = remoteDomainReadEventIOError(conn, xdr);
break;
+ case REMOTE_PROC_DOMAIN_EVENT_GRAPHICS:
+ event = remoteDomainReadEventGraphics(conn, xdr);
+ break;
+
default:
DEBUG("Unexpected event proc %d", hdr->proc);
break;
return TRUE;
}
+bool_t
+xdr_remote_domain_event_graphics_address (XDR *xdrs, remote_domain_event_graphics_address *objp)
+{
+
+ if (!xdr_int (xdrs, &objp->family))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->node))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->service))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_event_graphics_identity (XDR *xdrs, remote_domain_event_graphics_identity *objp)
+{
+
+ if (!xdr_remote_nonnull_string (xdrs, &objp->type))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_remote_domain_event_graphics_msg (XDR *xdrs, remote_domain_event_graphics_msg *objp)
+{
+ char **objp_cpp0 = (char **) (void *) &objp->subject.subject_val;
+
+ if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->phase))
+ return FALSE;
+ if (!xdr_remote_domain_event_graphics_address (xdrs, &objp->local))
+ return FALSE;
+ if (!xdr_remote_domain_event_graphics_address (xdrs, &objp->remote))
+ return FALSE;
+ if (!xdr_remote_nonnull_string (xdrs, &objp->authScheme))
+ return FALSE;
+ if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->subject.subject_len, REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX,
+ sizeof (remote_domain_event_graphics_identity), (xdrproc_t) xdr_remote_domain_event_graphics_identity))
+ return FALSE;
+ return TRUE;
+}
+
bool_t
xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
{
int action;
};
typedef struct remote_domain_event_io_error_msg remote_domain_event_io_error_msg;
+
+struct remote_domain_event_graphics_address {
+ int family;
+ remote_nonnull_string node;
+ remote_nonnull_string service;
+};
+typedef struct remote_domain_event_graphics_address remote_domain_event_graphics_address;
+#define REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX 20
+
+struct remote_domain_event_graphics_identity {
+ remote_nonnull_string type;
+ remote_nonnull_string name;
+};
+typedef struct remote_domain_event_graphics_identity remote_domain_event_graphics_identity;
+
+struct remote_domain_event_graphics_msg {
+ remote_nonnull_domain dom;
+ int phase;
+ remote_domain_event_graphics_address local;
+ remote_domain_event_graphics_address remote;
+ remote_nonnull_string authScheme;
+ struct {
+ u_int subject_len;
+ remote_domain_event_graphics_identity *subject_val;
+ } subject;
+};
+typedef struct remote_domain_event_graphics_msg remote_domain_event_graphics_msg;
#define REMOTE_PROGRAM 0x20008086
#define REMOTE_PROTOCOL_VERSION 1
REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE = 170,
REMOTE_PROC_DOMAIN_EVENT_WATCHDOG = 171,
REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172,
+ REMOTE_PROC_DOMAIN_EVENT_GRAPHICS = 173,
};
typedef enum remote_procedure remote_procedure;
extern bool_t xdr_remote_domain_event_rtc_change_msg (XDR *, remote_domain_event_rtc_change_msg*);
extern bool_t xdr_remote_domain_event_watchdog_msg (XDR *, remote_domain_event_watchdog_msg*);
extern bool_t xdr_remote_domain_event_io_error_msg (XDR *, remote_domain_event_io_error_msg*);
+extern bool_t xdr_remote_domain_event_graphics_address (XDR *, remote_domain_event_graphics_address*);
+extern bool_t xdr_remote_domain_event_graphics_identity (XDR *, remote_domain_event_graphics_identity*);
+extern bool_t xdr_remote_domain_event_graphics_msg (XDR *, remote_domain_event_graphics_msg*);
extern bool_t xdr_remote_procedure (XDR *, remote_procedure*);
extern bool_t xdr_remote_message_type (XDR *, remote_message_type*);
extern bool_t xdr_remote_message_status (XDR *, remote_message_status*);
extern bool_t xdr_remote_domain_event_rtc_change_msg ();
extern bool_t xdr_remote_domain_event_watchdog_msg ();
extern bool_t xdr_remote_domain_event_io_error_msg ();
+extern bool_t xdr_remote_domain_event_graphics_address ();
+extern bool_t xdr_remote_domain_event_graphics_identity ();
+extern bool_t xdr_remote_domain_event_graphics_msg ();
extern bool_t xdr_remote_procedure ();
extern bool_t xdr_remote_message_type ();
extern bool_t xdr_remote_message_status ();
int action;
};
+struct remote_domain_event_graphics_address {
+ int family;
+ remote_nonnull_string node;
+ remote_nonnull_string service;
+};
+
+const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
+
+struct remote_domain_event_graphics_identity {
+ remote_nonnull_string type;
+ remote_nonnull_string name;
+};
+
+struct remote_domain_event_graphics_msg {
+ remote_nonnull_domain dom;
+ int phase;
+ remote_domain_event_graphics_address local;
+ remote_domain_event_graphics_address remote;
+ remote_nonnull_string authScheme;
+ remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
+};
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE = 170,
REMOTE_PROC_DOMAIN_EVENT_WATCHDOG = 171,
- REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172
+ REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172,
+ REMOTE_PROC_DOMAIN_EVENT_GRAPHICS = 173
/*
* Notice how the entries are grouped in sets of 10 ?