]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virNetClientStream: Wire up VIR_NET_STREAM_HOLE
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 20 May 2016 14:35:13 +0000 (16:35 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Thu, 18 May 2017 05:42:13 +0000 (07:42 +0200)
Whenever server sends a client stream packet (either regular with
actual data or stream skip one) it is queued on @st->rx. So the
list is a mixture of both types of stream packets. So now that we
have all the helpers needed we can wire their processing up. But
since virNetClientStreamRecvPacket doesn't support
VIR_STREAM_RECV_STOP_AT_HOLE flag yet, let's turn all received
skips into zeroes repeating requested times.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
src/rpc/virnetclientstream.c

index 53378ff997aeb813dfb1f10fc27d2f8de3997c39..c22b6661e5962a50fa66154bcce86c425ffbdede 100644 (file)
@@ -296,6 +296,8 @@ int virNetClientStreamQueuePacket(virNetClientStreamPtr st,
 
     virObjectLock(st);
 
+    /* Don't distinguish VIR_NET_STREAM and VIR_NET_STREAM_SKIP
+     * here just yet. We want in order processing! */
     virNetMessageQueuePush(&st->rx, tmp_msg);
 
     virNetClientStreamEventTimerUpdate(st);
@@ -391,7 +393,7 @@ virNetClientStreamSetHole(virNetClientStreamPtr st,
  * Returns: 0 on success,
  *          -1 otherwise.
  */
-static int ATTRIBUTE_UNUSED
+static int
 virNetClientStreamHandleHole(virNetClientPtr client,
                              virNetClientStreamPtr st)
 {
@@ -469,6 +471,8 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
     virCheckFlags(0, -1);
 
     virObjectLock(st);
+
+ reread:
     if (!st->rx && !st->incomingEOF) {
         virNetMessagePtr msg;
         int ret;
@@ -500,8 +504,45 @@ int virNetClientStreamRecvPacket(virNetClientStreamPtr st,
     }
 
     VIR_DEBUG("After IO rx=%p", st->rx);
+
+    if (st->rx &&
+        st->rx->header.type == VIR_NET_STREAM_HOLE &&
+        st->holeLength == 0) {
+        /* Handle skip sent to us by server. */
+
+        if (virNetClientStreamHandleHole(client, st) < 0)
+            goto cleanup;
+    }
+
+    if (!st->rx && !st->incomingEOF && st->holeLength == 0) {
+        if (nonblock) {
+            VIR_DEBUG("Non-blocking mode and no data available");
+            rv = -2;
+            goto cleanup;
+        }
+
+        /* We have consumed all packets from incoming queue but those
+         * were only skip packets, no data. Read the stream again. */
+        goto reread;
+    }
+
     want = nbytes;
-    while (want && st->rx) {
+
+    if (st->holeLength) {
+        /* Pretend holeLength zeroes was read from stream. */
+        size_t len = want;
+
+        if (len > st->holeLength)
+            len = st->holeLength;
+
+        memset(data, 0, len);
+        st->holeLength -= len;
+        want -= len;
+    }
+
+    while (want &&
+           st->rx &&
+           st->rx->header.type == VIR_NET_STREAM) {
         virNetMessagePtr msg = st->rx;
         size_t len = want;