#include "virlog.h"
#include "virnetserverclient.h"
#include "virerror.h"
+#include "libvirt_internal.h"
#define VIR_FROM_THIS VIR_FROM_STREAMS
bool tx;
bool allowSkip;
+ size_t dataLen; /* How much data is there remaining until we see a hole */
daemonClientStreamPtr next;
};
size_t bufferLen = VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX;
int ret = -1;
int rv;
+ int inData = 0;
+ long long length = 0;
VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d",
client, stream, stream->tx, stream->closed);
if (!(msg = virNetMessageNew(false)))
goto cleanup;
+ if (stream->allowSkip && stream->dataLen == 0) {
+ /* Handle skip. We want to send some data to the client. But we might
+ * be in a hole. Seek to next data. But if we are in data already, just
+ * carry on. */
+
+ rv = virStreamInData(stream->st, &inData, &length);
+ VIR_DEBUG("rv=%d inData=%d length=%lld", rv, inData, length);
+
+ if (rv < 0) {
+ if (virNetServerProgramSendStreamError(remoteProgram,
+ client,
+ msg,
+ &rerr,
+ stream->procedure,
+ stream->serial) < 0)
+ goto cleanup;
+ msg = NULL;
+
+ /* We're done with this call */
+ goto done;
+ } else {
+ if (!inData && length) {
+ stream->tx = false;
+ msg->cb = daemonStreamMessageFinished;
+ msg->opaque = stream;
+ stream->refs++;
+ if (virNetServerProgramSendStreamHole(remoteProgram,
+ client,
+ msg,
+ stream->procedure,
+ stream->serial,
+ length,
+ 0) < 0)
+ goto cleanup;
+
+ msg = NULL;
+
+ /* We have successfully sent stream skip to the other side.
+ * To keep streams in sync seek locally too. */
+ virStreamSendHole(stream->st, length, 0);
+ /* We're done with this call */
+ goto done;
+ }
+ }
+
+ stream->dataLen = length;
+ }
+
+ if (stream->allowSkip &&
+ bufferLen > stream->dataLen)
+ bufferLen = stream->dataLen;
+
rv = virStreamRecv(stream->st, buffer, bufferLen);
if (rv == -2) {
/* Should never get this, since we're only called when we know
goto cleanup;
msg = NULL;
} else {
+ if (stream->allowSkip)
+ stream->dataLen -= rv;
+
stream->tx = false;
if (rv == 0)
stream->recvEOF = true;
msg = NULL;
}
+ done:
ret = 0;
cleanup:
VIR_FREE(buffer);