[PATCH v2 2/3] rpc: Introduce virNetClientStreamInData()

Michal Privoznik mprivozn at redhat.com
Thu Dec 9 08:44:22 UTC 2021


The aim of this function is to look at a virNetClientStream and
tell whether the incoming packet (if there's one) contains data
(type VIR_NET_STREAM) or a hole (type VIR_NET_STREAM_HOLE) and
how big the section is. This function will be called from the
remote driver in one of future commits.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
diff to v1:
  - initialize ret to -1
  - lock stream even for checking allowSkip
  - return 1 only if message was really popped from the queue
  - If there's no incoming message, return the size of yet unprocessed
    hole. This size should always be zero though, because at EOF there's
    a hole of size 0. I have not met this case and I probably never
    will, but I figured it's better to be safe than sorry.


 src/libvirt_remote.syms      |  1 +
 src/rpc/virnetclientstream.c | 64 ++++++++++++++++++++++++++++++++++++
 src/rpc/virnetclientstream.h |  4 +++
 3 files changed, 69 insertions(+)

diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index 942e1013a6..07d22e368b 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -66,6 +66,7 @@ virNetClientStreamEOF;
 virNetClientStreamEventAddCallback;
 virNetClientStreamEventRemoveCallback;
 virNetClientStreamEventUpdateCallback;
+virNetClientStreamInData;
 virNetClientStreamMatches;
 virNetClientStreamNew;
 virNetClientStreamQueuePacket;
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 1ba6167a1d..eb4dc6854d 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -801,3 +801,67 @@ bool virNetClientStreamEOF(virNetClientStream *st)
 {
     return st->incomingEOF;
 }
+
+
+int virNetClientStreamInData(virNetClientStream *st,
+                             int *inData,
+                             long long *length)
+{
+    int ret = -1;
+    bool msgPopped = false;
+    virNetMessage *msg = NULL;
+
+    virObjectLock(st);
+
+    if (!st->allowSkip) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("Holes are not supported with this stream"));
+        goto cleanup;
+    }
+
+    if (virNetClientStreamCheckState(st) < 0)
+        goto cleanup;
+
+    msg = st->rx;
+
+    if (!msg) {
+        /* No incoming message. This means that the stream is at its end. In
+         * this case, virStreamInData() should set both inData and length to
+         * zero and return success. If there is a trailing hole though (there
+         * shouldn't be), signal that to the caller. */
+        *inData = 0;
+        *length = st->holeLength;
+        st->holeLength = 0;
+    } else if (msg->header.type == VIR_NET_STREAM) {
+        *inData = 1;
+        *length = msg->bufferLength - msg->bufferOffset;
+    } else if (msg->header.type == VIR_NET_STREAM_HOLE) {
+        *inData = 0;
+
+        if (st->holeLength == 0) {
+            if (virNetClientStreamHandleHole(NULL, st) < 0)
+                goto cleanup;
+
+            /* virNetClientStreamHandleHole() called above did pop the message from
+             * the queue (and freed it). Instead of trying to push it back let's
+             * just signal to the caller what we did. */
+            msgPopped = true;
+        }
+
+        *length = st->holeLength;
+        st->holeLength = 0;
+    } else {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Invalid message prog=%d type=%d serial=%u proc=%d"),
+                       msg->header.prog,
+                       msg->header.type,
+                       msg->header.serial,
+                       msg->header.proc);
+        goto cleanup;
+    }
+
+    ret = msgPopped ? 1 : 0;
+ cleanup:
+    virObjectUnlock(st);
+    return ret;
+}
diff --git a/src/rpc/virnetclientstream.h b/src/rpc/virnetclientstream.h
index e16d6e4a9a..7428843f9b 100644
--- a/src/rpc/virnetclientstream.h
+++ b/src/rpc/virnetclientstream.h
@@ -90,3 +90,7 @@ int virNetClientStreamEventRemoveCallback(virNetClientStream *st);
 
 bool virNetClientStreamEOF(virNetClientStream *st)
     ATTRIBUTE_NONNULL(1);
+
+int virNetClientStreamInData(virNetClientStream *st,
+                             int *inData,
+                             long long *length);
-- 
2.32.0




More information about the libvir-list mailing list