Example #1
0
/*
 * Invoked when a stream is signalled as having data
 * available to read. This reads upto one message
 * worth of data, and then queues that for transmission
 * to the client.
 *
 * Returns 0 if data was queued for TX, or a error RPC
 * was sent, or -1 on fatal error, indicating client should
 * be killed
 */
static int
remoteStreamHandleRead(struct qemud_client *client,
                       struct qemud_client_stream *stream)
{
    char *buffer;
    size_t bufferLen = REMOTE_MESSAGE_PAYLOAD_MAX;
    int ret;

    VIR_DEBUG("stream=%p", stream);

    /* Shouldn't ever be called unless we're marked able to
     * transmit, but doesn't hurt to check */
    if (!stream->tx)
        return 0;

    if (VIR_ALLOC_N(buffer, bufferLen) < 0)
        return -1;

    ret = virStreamRecv(stream->st, buffer, bufferLen);
    if (ret == -2) {
        /* Should never get this, since we're only called when we know
         * we're readable, but hey things change... */
        ret = 0;
    } else if (ret < 0) {
        remote_error rerr;
        memset(&rerr, 0, sizeof rerr);
        remoteDispatchError(&rerr);

        ret = remoteSerializeStreamError(client, &rerr, stream->procedure, stream->serial);
    } else {
        stream->tx = 0;
        if (ret == 0)
            stream->recvEOF = 1;
        ret = remoteSendStreamData(client, stream, buffer, ret);
    }

    VIR_FREE(buffer);
    return ret;
}
Example #2
0
/*
 * Invoked when a stream is signalled as having data
 * available to read. This reads up to one message
 * worth of data, and then queues that for transmission
 * to the client.
 *
 * Returns 0 if data was queued for TX, or a error RPC
 * was sent, or -1 on fatal error, indicating client should
 * be killed
 */
static int
daemonStreamHandleRead(virNetServerClientPtr client,
                       daemonClientStream *stream)
{
    char *buffer;
    size_t bufferLen = VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX;
    int ret;

    VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d",
              client, stream, stream->tx, stream->closed);

    /* We might have had an event pending before we shut
     * down the stream, so if we're marked as closed,
     * then do nothing
     */
    if (stream->closed)
        return 0;

    /* Shouldn't ever be called unless we're marked able to
     * transmit, but doesn't hurt to check */
    if (!stream->tx)
        return 0;

    if (VIR_ALLOC_N(buffer, bufferLen) < 0)
        return -1;

    ret = virStreamRecv(stream->st, buffer, bufferLen);
    if (ret == -2) {
        /* Should never get this, since we're only called when we know
         * we're readable, but hey things change... */
        ret = 0;
    } else if (ret < 0) {
        virNetMessagePtr msg;
        virNetMessageError rerr;

        memset(&rerr, 0, sizeof(rerr));

        if (!(msg = virNetMessageNew(false)))
            ret = -1;
        else
            ret = virNetServerProgramSendStreamError(remoteProgram,
                                                     client,
                                                     msg,
                                                     &rerr,
                                                     stream->procedure,
                                                     stream->serial);
    } else {
        virNetMessagePtr msg;
        stream->tx = 0;
        if (ret == 0)
            stream->recvEOF = 1;
        if (!(msg = virNetMessageNew(false)))
            ret = -1;

        if (msg) {
            msg->cb = daemonStreamMessageFinished;
            msg->opaque = stream;
            stream->refs++;
            ret = virNetServerProgramSendStreamData(remoteProgram,
                                                    client,
                                                    msg,
                                                    stream->procedure,
                                                    stream->serial,
                                                    buffer, ret);
        }
    }

    VIR_FREE(buffer);
    return ret;
}
Example #3
0
static void
virConsoleEventOnStream(virStreamPtr st,
                        int events, void *opaque)
{
    virConsolePtr con = opaque;

    if (events & VIR_STREAM_EVENT_READABLE) {
        size_t avail = con->streamToTerminal.length -
            con->streamToTerminal.offset;
        int got;

        if (avail < 1024) {
            if (VIR_REALLOC_N(con->streamToTerminal.data,
                              con->streamToTerminal.length + 1024) < 0) {
                virReportOOMError();
                virConsoleShutdown(con);
                return;
            }
            con->streamToTerminal.length += 1024;
            avail += 1024;
        }

        got = virStreamRecv(st,
                            con->streamToTerminal.data +
                            con->streamToTerminal.offset,
                            avail);
        if (got == -2)
            return; /* blocking */
        if (got <= 0) {
            virConsoleShutdown(con);
            return;
        }
        con->streamToTerminal.offset += got;
        if (con->streamToTerminal.offset)
            virEventUpdateHandle(con->stdoutWatch,
                                 VIR_EVENT_HANDLE_WRITABLE);
    }

    if (events & VIR_STREAM_EVENT_WRITABLE &&
        con->terminalToStream.offset) {
        ssize_t done;
        size_t avail;
        done = virStreamSend(con->st,
                             con->terminalToStream.data,
                             con->terminalToStream.offset);
        if (done == -2)
            return; /* blocking */
        if (done < 0) {
            virConsoleShutdown(con);
            return;
        }
        memmove(con->terminalToStream.data,
                con->terminalToStream.data + done,
                con->terminalToStream.offset - done);
        con->terminalToStream.offset -= done;

        avail = con->terminalToStream.length - con->terminalToStream.offset;
        if (avail > 1024) {
            if (VIR_REALLOC_N(con->terminalToStream.data,
                              con->terminalToStream.offset + 1024) < 0)
            {}
            con->terminalToStream.length = con->terminalToStream.offset + 1024;
        }
    }
    if (!con->terminalToStream.offset)
        virStreamEventUpdateCallback(con->st,
                                     VIR_STREAM_EVENT_READABLE);

    if (events & VIR_STREAM_EVENT_ERROR ||
        events & VIR_STREAM_EVENT_HANGUP) {
        virConsoleShutdown(con);
    }
}
Example #4
0
static void
virConsoleEventOnStream(virStreamPtr st,
                        int events, void *opaque)
{
    virConsolePtr con = opaque;

    virObjectLock(con);

    /* we got late event after console was shutdown */
    if (!con->st)
        goto cleanup;

    if (events & VIR_STREAM_EVENT_READABLE) {
        size_t avail = con->streamToTerminal.length -
            con->streamToTerminal.offset;
        int got;

        if (avail < 1024) {
            if (VIR_REALLOC_N(con->streamToTerminal.data,
                              con->streamToTerminal.length + 1024) < 0) {
                virConsoleShutdown(con);
                goto cleanup;
            }
            con->streamToTerminal.length += 1024;
            avail += 1024;
        }

        got = virStreamRecv(st,
                            con->streamToTerminal.data +
                            con->streamToTerminal.offset,
                            avail);
        if (got == -2)
            goto cleanup; /* blocking */
        if (got <= 0) {
            if (got == 0)
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("console stream EOF"));

            virConsoleShutdown(con);
            goto cleanup;
        }
        con->streamToTerminal.offset += got;
        if (con->streamToTerminal.offset)
            virEventUpdateHandle(con->stdoutWatch,
                                 VIR_EVENT_HANDLE_WRITABLE);
    }

    if (events & VIR_STREAM_EVENT_WRITABLE &&
        con->terminalToStream.offset) {
        ssize_t done;
        size_t avail;
        done = virStreamSend(con->st,
                             con->terminalToStream.data,
                             con->terminalToStream.offset);
        if (done == -2)
            goto cleanup; /* blocking */
        if (done < 0) {
            virConsoleShutdown(con);
            goto cleanup;
        }
        memmove(con->terminalToStream.data,
                con->terminalToStream.data + done,
                con->terminalToStream.offset - done);
        con->terminalToStream.offset -= done;

        avail = con->terminalToStream.length - con->terminalToStream.offset;
        if (avail > 1024) {
            ignore_value(VIR_REALLOC_N(con->terminalToStream.data,
                                       con->terminalToStream.offset + 1024));
            con->terminalToStream.length = con->terminalToStream.offset + 1024;
        }
    }
    if (!con->terminalToStream.offset)
        virStreamEventUpdateCallback(con->st,
                                     VIR_STREAM_EVENT_READABLE);

    if (events & VIR_STREAM_EVENT_ERROR ||
        events & VIR_STREAM_EVENT_HANGUP) {
        virConsoleShutdown(con);
    }

 cleanup:
    virObjectUnlock(con);
}
Result StorageVolControlThread::downloadStorageVol()
{
    Result result;
    result.name = QString("%1_%2").arg(task.srcConName).arg(currPoolName);
    QString name, path;
    name = task.object;
    path = task.args.path;
    //qDebug()<<args.first()<<"download";
    if (currStoragePool!=NULL) {
        virStoragePoolFree(currStoragePool);
        currStoragePool = NULL;
    };
    currStoragePool = virStoragePoolLookupByName(
                *task.srcConnPtr, currPoolName.toUtf8().data());
    QFile *f = new QFile(path);
    f->open(QIODevice::WriteOnly);

    bool downloaded = false;
    virStreamPtr stream = virStreamNew(*task.srcConnPtr, 0);
    unsigned long long offset = 0;
    unsigned long long length = task.args.size;
    // flags: extra flags; not used yet, so callers should always pass 0
    unsigned int flags = 0;
    virStorageVol *storageVol = virStorageVolLookupByName(
                currStoragePool, name.toUtf8().data());
    if ( storageVol!=NULL ) {
        int ret = virStorageVolDownload(
                    storageVol, stream, offset, length, flags);
        if ( ret<0 )
            result.err = sendConnErrors();
        else {
            downloaded = true;
            length = 0;
            char buf[BLOCK_SIZE];
            int got, saved, step;
            step = 0;
            while ( 1 && keep_alive ) {
                got = virStreamRecv(stream, buf, BLOCK_SIZE);
                if (got < 0) {
                    result.err = sendConnErrors();
                    downloaded = false;
                    break;
                };
                if (got == 0) break;
                step++;
                saved = f->write(buf, got);
                //qDebug()<<"got<>saved"<<got<<saved<<step;
                if ( saved+1 ) length += saved;
                else {
                    QString msg = QString("WriteError after (%2): %1 bytes")
                            .arg(length).arg(step);
                    emit errorMsg( msg, number );
                    result.err = msg;
                };
            };
            virStreamFinish(stream);
        };
        virStorageVolFree(storageVol);
    } else sendConnErrors();
    if ( stream!=NULL ) virStreamFree(stream);
    f->close();
    delete f; f = NULL;
    result.msg.append(
                QString("'<b>%1</b>' StorageVol %2 Downloaded into %3 (%4).")
                .arg(name).arg((downloaded)?"":"don't")
                .arg(path).arg(length));
    result.result = downloaded;
    return result;
}