}
+static void remoteClientCloseFunc(virNetServerClientPtr client)
+{
+ struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client);
+
+ daemonRemoveAllClientStreams(priv->streams);
+}
+
int remoteClientInitHook(virNetServerPtr srv ATTRIBUTE_UNUSED,
virNetServerClientPtr client)
for (i = 0 ; i < VIR_DOMAIN_EVENT_ID_LAST ; i++)
priv->domainEventCallbackID[i] = -1;
- virNetServerClientSetPrivateData(client, priv, remoteClientFreeFunc);
+ virNetServerClientSetPrivateData(client, priv,
+ remoteClientFreeFunc);
+ virNetServerClientSetCloseHook(client, remoteClientCloseFunc);
return 0;
}
msg = stream->rx;
while (msg) {
virNetMessagePtr tmp = msg->next;
- /* Send a dummy reply to free up 'msg' & unblock client rx */
- memset(msg, 0, sizeof(*msg));
- msg->header.type = VIR_NET_REPLY;
- if (virNetServerClientSendMessage(client, msg) < 0) {
- virNetServerClientImmediateClose(client);
+ if (client) {
+ /* Send a dummy reply to free up 'msg' & unblock client rx */
+ memset(msg, 0, sizeof(*msg));
+ msg->header.type = VIR_NET_REPLY;
+ if (virNetServerClientSendMessage(client, msg) < 0) {
+ virNetServerClientImmediateClose(client);
+ virNetMessageFree(msg);
+ ret = -1;
+ }
+ } else {
virNetMessageFree(msg);
- ret = -1;
}
msg = tmp;
}
}
+void
+daemonRemoveAllClientStreams(daemonClientStream *stream)
+{
+ daemonClientStream *tmp;
+
+ VIR_DEBUG("stream=%p", stream);
+
+ while (stream) {
+ tmp = stream->next;
+
+ if (!stream->closed) {
+ virStreamEventRemoveCallback(stream->st);
+ virStreamAbort(stream->st);
+ }
+
+ daemonFreeClientStream(NULL, stream);
+
+ VIR_DEBUG("next stream=%p", tmp);
+ stream = tmp;
+ }
+}
+
/*
* Returns:
* -1 if fatal error occurred
daemonRemoveClientStream(virNetServerClientPtr client,
daemonClientStream *stream);
+void
+daemonRemoveAllClientStreams(daemonClientStream *stream);
+
#endif /* __LIBVIRTD_STREAM_H__ */
void *privateData;
virNetServerClientFreeFunc privateDataFreeFunc;
+ virNetServerClientCloseFunc privateDataCloseFunc;
};
}
+void virNetServerClientSetCloseHook(virNetServerClientPtr client,
+ virNetServerClientCloseFunc cf)
+{
+ virNetServerClientLock(client);
+ client->privateDataCloseFunc = cf;
+ virNetServerClientUnlock(client);
+}
+
+
void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func,
void *opaque)
*/
void virNetServerClientClose(virNetServerClientPtr client)
{
+ virNetServerClientCloseFunc cf;
+
virNetServerClientLock(client);
VIR_DEBUG("client=%p refs=%d", client, client->refs);
if (!client->sock) {
return;
}
+ if (client->privateDataCloseFunc) {
+ cf = client->privateDataCloseFunc;
+ client->refs++;
+ virNetServerClientUnlock(client);
+ (cf)(client);
+ virNetServerClientLock(client);
+ client->refs--;
+ }
+
/* Do now, even though we don't close the socket
* until end, to ensure we don't get invoked
* again due to tls shutdown */
virNetServerClientFreeFunc ff);
void *virNetServerClientGetPrivateData(virNetServerClientPtr client);
+typedef void (*virNetServerClientCloseFunc)(virNetServerClientPtr client);
+
+void virNetServerClientSetCloseHook(virNetServerClientPtr client,
+ virNetServerClientCloseFunc cf);
+
void virNetServerClientSetDispatcher(virNetServerClientPtr client,
virNetServerClientDispatchFunc func,
void *opaque);