size_t nnetworkEventCallbacks;
daemonClientEventCallbackPtr *qemuEventCallbacks;
size_t nqemuEventCallbacks;
+ bool closeRegistered;
# if WITH_SASL
virNetSASLSessionPtr sasl;
VIR_FREE(details_p);
}
+static
+void remoteRelayConnectionClosedEvent(virConnectPtr conn ATTRIBUTE_UNUSED, int reason, void *opaque)
+{
+ virNetServerClientPtr client = opaque;
+
+ VIR_DEBUG("Relaying connection closed event, reason %d", reason);
+
+ remote_connect_event_connection_closed_msg msg = { reason };
+ remoteDispatchObjectEventSend(client, remoteProgram,
+ REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED,
+ (xdrproc_t)xdr_remote_connect_event_connection_closed_msg,
+ &msg);
+}
+
/*
* You must hold lock for at least the client
* We don't free stuff here, merely disconnect the client's
}
VIR_FREE(priv->qemuEventCallbacks);
+ if (priv->closeRegistered) {
+ if (virConnectUnregisterCloseCallback(priv->conn,
+ remoteRelayConnectionClosedEvent) < 0)
+ VIR_WARN("unexpected close callback event deregister failure");
+ }
+
virConnectClose(priv->conn);
virIdentitySetCurrent(NULL);
return rv;
}
+static int
+remoteDispatchConnectCloseCallbackRegister(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr)
+{
+ int rv = -1;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ virMutexLock(&priv->lock);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ // on behalf of close callback
+ virObjectRef(client);
+ if (virConnectRegisterCloseCallback(priv->conn,
+ remoteRelayConnectionClosedEvent,
+ client, virObjectFreeCallback) < 0)
+ goto cleanup;
+
+ priv->closeRegistered = true;
+ rv = 0;
+
+ cleanup:
+ virMutexUnlock(&priv->lock);
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ return rv;
+}
+
+static int
+remoteDispatchConnectCloseCallbackUnregister(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr)
+{
+ int rv = -1;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ virMutexLock(&priv->lock);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ if (virConnectUnregisterCloseCallback(priv->conn,
+ remoteRelayConnectionClosedEvent) < 0)
+ goto cleanup;
+
+ priv->closeRegistered = false;
+ rv = 0;
+
+ cleanup:
+ virMutexUnlock(&priv->lock);
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ return rv;
+}
/***************************
* Register / deregister events
switch (args->feature) {
case VIR_DRV_FEATURE_FD_PASSING:
case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+ case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
supported = 1;
break;
* Support for server-side event filtering via callback ids in events.
*/
VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK = 14,
+
+ /*
+ * Support for driver close callback rpc
+ */
+ VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK = 15,
};
char *hostname; /* Original hostname */
bool serverKeepAlive; /* Does server support keepalive protocol? */
bool serverEventFilter; /* Does server support modern event filtering */
+ bool serverCloseCallback; /* Does server support driver close callback */
virObjectEventStatePtr eventState;
virConnectCloseCallbackDataPtr closeCallback;
virNetClientPtr client ATTRIBUTE_UNUSED,
void *evdata, void *opaque);
+static void
+remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque);
+
static virNetClientProgramEvent remoteEvents[] = {
{ REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
remoteDomainBuildEventLifecycle,
remoteDomainBuildEventCallbackMigrationIteration,
sizeof(remote_domain_event_callback_migration_iteration_msg),
(xdrproc_t)xdr_remote_domain_event_callback_migration_iteration_msg },
+ { REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED,
+ remoteConnectNotifyEventConnectionClosed,
+ sizeof(remote_connect_event_connection_closed_msg),
+ (xdrproc_t)xdr_remote_connect_event_connection_closed_msg },
};
+static void
+remoteConnectNotifyEventConnectionClosed(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+ virNetClientPtr client ATTRIBUTE_UNUSED,
+ void *evdata, void *opaque)
+{
+ virConnectPtr conn = opaque;
+ struct private_data *priv = conn->privateData;
+ remote_connect_event_connection_closed_msg *msg = evdata;
+
+ virConnectCloseCallbackDataCall(priv->closeCallback, msg->reason);
+}
static void
remoteDomainBuildQemuMonitorEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
"supported by the server");
}
+ priv->serverCloseCallback = remoteConnectSupportsFeatureUnlocked(conn,
+ priv, VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK);
+ if (!priv->serverCloseCallback) {
+ VIR_INFO("Close callback registering isn't supported "
+ "by the remote side.");
+ }
+
/* Successful. */
retcode = VIR_DRV_OPEN_SUCCESS;
goto cleanup;
}
+ if (priv->serverCloseCallback &&
+ call(conn, priv, 0, REMOTE_PROC_CONNECT_CLOSE_CALLBACK_REGISTER,
+ (xdrproc_t) xdr_void, (char *) NULL,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto cleanup;
+
virConnectCloseCallbackDataRegister(priv->closeCallback, conn, cb,
opaque, freecb);
ret = 0;
goto cleanup;
}
+ if (priv->serverCloseCallback &&
+ call(conn, priv, 0, REMOTE_PROC_CONNECT_CLOSE_CALLBACK_UNREGISTER,
+ (xdrproc_t) xdr_void, (char *) NULL,
+ (xdrproc_t) xdr_void, (char *) NULL) == -1)
+ goto cleanup;
+
virConnectCloseCallbackDataUnregister(priv->closeCallback, cb);
ret = 0;
remote_nonnull_string devAlias;
};
+struct remote_connect_event_connection_closed_msg {
+ int reason;
+};
+
struct remote_connect_get_cpu_model_names_args {
remote_nonnull_string arch;
int need_results;
* @generate: both
* @acl: none
*/
- REMOTE_PROC_DOMAIN_EVENT_CALLBACK_MIGRATION_ITERATION = 359
+ REMOTE_PROC_DOMAIN_EVENT_CALLBACK_MIGRATION_ITERATION = 359,
+
+ /**
+ * @generate: none
+ * @acl: none
+ */
+ REMOTE_PROC_CONNECT_CLOSE_CALLBACK_REGISTER = 360,
+
+ /**
+ * @generate: none
+ * @acl: none
+ */
+ REMOTE_PROC_CONNECT_CLOSE_CALLBACK_UNREGISTER = 361,
+
+ /**
+ * @generate: none
+ * @acl: none
+ */
+ REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED = 362
};
remote_nonnull_domain dom;
remote_nonnull_string devAlias;
};
+struct remote_connect_event_connection_closed_msg {
+ int reason;
+};
struct remote_connect_get_cpu_model_names_args {
remote_nonnull_string arch;
int need_results;
REMOTE_PROC_DOMAIN_SET_USER_PASSWORD = 357,
REMOTE_PROC_DOMAIN_RENAME = 358,
REMOTE_PROC_DOMAIN_EVENT_CALLBACK_MIGRATION_ITERATION = 359,
+ REMOTE_PROC_CONNECT_CLOSE_CALLBACK_REGISTER = 360,
+ REMOTE_PROC_CONNECT_CLOSE_CALLBACK_UNREGISTER = 361,
+ REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED = 362,
};