Exemplo n.º 1
0
/*
 * Process an abort request from the client.
 *
 * Returns 0 if successfully aborted, -1 upon error
 */
static int
daemonStreamHandleAbort(virNetServerClientPtr client,
                        daemonClientStream *stream,
                        virNetMessagePtr msg)
{
    VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d",
              client, stream, msg->header.proc, msg->header.serial);
    virNetMessageError rerr;

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

    stream->closed = 1;
    virStreamEventRemoveCallback(stream->st);
    virStreamAbort(stream->st);

    if (msg->header.status == VIR_NET_ERROR)
        virReportError(VIR_ERR_RPC,
                       "%s", _("stream aborted at client request"));
    else {
        VIR_WARN("unexpected stream status %d", msg->header.status);
        virReportError(VIR_ERR_RPC,
                       _("stream aborted with unexpected status %d"),
                       msg->header.status);
    }

    return virNetServerProgramSendReplyError(remoteProgram,
                                             client,
                                             msg,
                                             &rerr,
                                             &msg->header);
}
Exemplo n.º 2
0
/*
 * @client: a locked client object
 * @stream: an inactive, closed stream object
 *
 * Removes a stream from the list of active streams for the client
 *
 * Returns 0 if the stream was removd, -1 if it doesn't exist
 */
int
daemonRemoveClientStream(virNetServerClientPtr client,
                         daemonClientStream *stream)
{
    VIR_DEBUG("client=%p, proc=%d, serial=%d, st=%p",
              client, stream->procedure, stream->serial, stream->st);
    daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);
    daemonClientStream *curr = priv->streams;
    daemonClientStream *prev = NULL;

    if (stream->filterID != -1) {
        virNetServerClientRemoveFilter(client,
                                       stream->filterID);
        stream->filterID = -1;
    }

    if (!stream->closed) {
        virStreamEventRemoveCallback(stream->st);
        virStreamAbort(stream->st);
    }

    while (curr) {
        if (curr == stream) {
            if (prev)
                prev->next = curr->next;
            else
                priv->streams = curr->next;
            return daemonFreeClientStream(client, stream);
        }
        prev = curr;
        curr = curr->next;
    }
    return -1;
}
Exemplo n.º 3
0
static void
virConsoleShutdown(virConsolePtr con)
{
    virErrorPtr err = virGetLastError();

    if (con->error.code == VIR_ERR_OK && err)
        virCopyLastError(&con->error);

    if (con->st) {
        virStreamEventRemoveCallback(con->st);
        virStreamAbort(con->st);
        virStreamFree(con->st);
        con->st = NULL;
    }
    VIR_FREE(con->streamToTerminal.data);
    VIR_FREE(con->terminalToStream.data);
    if (con->stdinWatch != -1)
        virEventRemoveHandle(con->stdinWatch);
    if (con->stdoutWatch != -1)
        virEventRemoveHandle(con->stdoutWatch);
    con->stdinWatch = -1;
    con->stdoutWatch = -1;
    if (!con->quit) {
        con->quit = true;
        virCondSignal(&con->cond);
    }
}
Exemplo n.º 4
0
/*
 * Process an abort request from the client.
 *
 * Returns 0 if successfully aborted, -1 upon error
 */
static int
remoteStreamHandleAbort(struct qemud_client *client,
                        struct qemud_client_stream *stream,
                        struct qemud_client_message *msg)
{
    remote_error rerr;

    VIR_DEBUG("stream=%p proc=%d serial=%d",
          stream, msg->hdr.proc, msg->hdr.serial);

    memset(&rerr, 0, sizeof rerr);

    stream->closed = 1;
    virStreamEventRemoveCallback(stream->st);
    virStreamAbort(stream->st);

    if (msg->hdr.status == REMOTE_ERROR)
        remoteDispatchFormatError(&rerr, "%s", _("stream aborted at client request"));
    else {
        VIR_WARN("unexpected stream status %d", msg->hdr.status);
        remoteDispatchFormatError(&rerr, _("stream aborted with unexpected status %d"),
                                  msg->hdr.status);
    }

    return remoteSerializeReplyError(client, &rerr, &msg->hdr);
}
// here be a compress func
void compressFunc(virConnectPtr conn)
{
	int fd;
	// открываем некомпрессированный файл
	// компрессуем
	
	virStreamPtr st = virStreamNew(conn, 0);
	fd = open("compressed_file", O_RDONLY);
// открываем компрессированный, считываем, передаём стрим - сенд по указателю на поток СТ, буф+смещение, до гот-смещение
	while (1) {
       		char buf[1024];
       		int got;
		got = read(fd, buf, 1024);
	       	if (got < 0) {
          	virStreamAbort(st);
          	break;
       		}
       	if (got == 0) {
       		virStreamFinish(st);
          	break;
       	}
       	int offset = 0;
       	while (offset < got) {
        	int sent;
          	sent = virStreamSend(st, buf+offset, got-offset);
          	if (sent < 0) {
             	virStreamAbort(st);
             	goto done;
        }
        offset += sent;
       }
   }
   if (virStreamFinish(st) < 0)
   	// обработчик ошибки
done:
   virStreamFree(st);
   close(fd);	
}
Exemplo n.º 6
0
static void
virConsoleShutdown(virConsolePtr con)
{
    if (con->st) {
        virStreamEventRemoveCallback(con->st);
        virStreamAbort(con->st);
        virStreamFree(con->st);
    }
    VIR_FREE(con->streamToTerminal.data);
    VIR_FREE(con->terminalToStream.data);
    if (con->stdinWatch != -1)
        virEventRemoveHandle(con->stdinWatch);
    if (con->stdoutWatch != -1)
        virEventRemoveHandle(con->stdoutWatch);
    con->stdinWatch = -1;
    con->stdoutWatch = -1;
    con->quit = true;
    virCondSignal(&con->cond);
}
Exemplo n.º 7
0
/*
 * @client: a locked client object
 * @stream: an inactive, closed stream object
 *
 * Removes a stream from the list of active streams for the client
 *
 * Returns 0 if the stream was removd, -1 if it doesn't exist
 */
int
remoteRemoveClientStream(struct qemud_client *client,
                         struct qemud_client_stream *stream)
{
    VIR_DEBUG("client=%p proc=%d serial=%d", client, stream->procedure, stream->serial);

    struct qemud_client_stream *curr = client->streams;
    struct qemud_client_stream *prev = NULL;
    struct qemud_client_filter *filter = NULL;

    if (client->filters == &stream->filter) {
        client->filters = client->filters->next;
    } else {
        filter = client->filters;
        while (filter) {
            if (filter->next == &stream->filter) {
                filter->next = filter->next->next;
                break;
            }
            filter = filter->next;
        }
    }

    if (!stream->closed) {
        virStreamEventRemoveCallback(stream->st);
        virStreamAbort(stream->st);
    }

    while (curr) {
        if (curr == stream) {
            if (prev)
                prev->next = curr->next;
            else
                client->streams = curr->next;
            remoteFreeClientStream(client, stream);
            return 0;
        }
        prev = curr;
        curr = curr->next;
    }
    return -1;
}
Exemplo n.º 8
0
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;
    }
}
Exemplo n.º 9
0
/*
 * Callback that gets invoked when a stream becomes writable/readable
 */
static void
daemonStreamEvent(virStreamPtr st, int events, void *opaque)
{
    virNetServerClientPtr client = opaque;
    daemonClientStream *stream;
    daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client);

    virMutexLock(&priv->lock);

    stream = priv->streams;
    while (stream) {
        if (stream->st == st)
            break;
        stream = stream->next;
    }

    if (!stream) {
        VIR_WARN("event for client=%p stream st=%p, but missing stream state", client, st);
        virStreamEventRemoveCallback(st);
        goto cleanup;
    }

    VIR_DEBUG("st=%p events=%d EOF=%d closed=%d", st, events, stream->recvEOF, stream->closed);

    if (!stream->closed &&
        (events & VIR_STREAM_EVENT_WRITABLE)) {
        if (daemonStreamHandleWrite(client, stream) < 0) {
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
    }

    if (!stream->closed && !stream->recvEOF &&
        (events & (VIR_STREAM_EVENT_READABLE))) {
        events = events & ~(VIR_STREAM_EVENT_READABLE);
        if (daemonStreamHandleRead(client, stream) < 0) {
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
        /* If we detected EOF during read processing,
         * then clear hangup/error conditions, since
         * we want the client to see the EOF message
         * we just sent them
         */
        if (stream->recvEOF)
            events = events & ~(VIR_STREAM_EVENT_HANGUP |
                                VIR_STREAM_EVENT_ERROR);
    }

    /* If we have a completion/abort message, always process it */
    if (stream->rx) {
        virNetMessagePtr msg = stream->rx;
        switch (msg->header.status) {
        case VIR_NET_CONTINUE:
            /* nada */
            break;
        case VIR_NET_OK:
            virNetMessageQueueServe(&stream->rx);
            if (daemonStreamHandleFinish(client, stream, msg) < 0) {
                virNetMessageFree(msg);
                daemonRemoveClientStream(client, stream);
                virNetServerClientClose(client);
                goto cleanup;
            }
            break;
        case VIR_NET_ERROR:
        default:
            virNetMessageQueueServe(&stream->rx);
            if (daemonStreamHandleAbort(client, stream, msg) < 0) {
                virNetMessageFree(msg);
                daemonRemoveClientStream(client, stream);
                virNetServerClientClose(client);
                goto cleanup;
            }
            break;
        }
    }


    /* If we got HANGUP, we need to only send an empty
     * packet so the client sees an EOF and cleans up
     */
    if (!stream->closed && !stream->recvEOF &&
        (events & VIR_STREAM_EVENT_HANGUP)) {
        virNetMessagePtr msg;
        events &= ~(VIR_STREAM_EVENT_HANGUP);
        stream->tx = 0;
        stream->recvEOF = 1;
        if (!(msg = virNetMessageNew(false))) {
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
        msg->cb = daemonStreamMessageFinished;
        msg->opaque = stream;
        stream->refs++;
        if (virNetServerProgramSendStreamData(remoteProgram,
                                              client,
                                              msg,
                                              stream->procedure,
                                              stream->serial,
                                              "", 0) < 0) {
            virNetMessageFree(msg);
            daemonRemoveClientStream(client, stream);
            virNetServerClientClose(client);
            goto cleanup;
        }
    }

    if (!stream->closed &&
        (events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) {
        int ret;
        virNetMessagePtr msg;
        virNetMessageError rerr;

        memset(&rerr, 0, sizeof(rerr));
        stream->closed = 1;
        virStreamEventRemoveCallback(stream->st);
        virStreamAbort(stream->st);
        if (events & VIR_STREAM_EVENT_HANGUP)
            virReportError(VIR_ERR_RPC,
                           "%s", _("stream had unexpected termination"));
        else
            virReportError(VIR_ERR_RPC,
                           "%s", _("stream had I/O failure"));

        msg = virNetMessageNew(false);
        if (!msg) {
            ret = -1;
        } else {
            ret = virNetServerProgramSendStreamError(remoteProgram,
                                                     client,
                                                     msg,
                                                     &rerr,
                                                     stream->procedure,
                                                     stream->serial);
        }
        daemonRemoveClientStream(client, stream);
        if (ret < 0)
            virNetServerClientClose(client);
        goto cleanup;
    }

    if (stream->closed) {
        daemonRemoveClientStream(client, stream);
    } else {
        daemonStreamUpdateEvents(stream);
    }

cleanup:
    virMutexUnlock(&priv->lock);
}
Exemplo n.º 10
0
/*
 * Callback that gets invoked when a stream becomes writable/readable
 */
static void
remoteStreamEvent(virStreamPtr st, int events, void *opaque)
{
    struct qemud_client *client = opaque;
    struct qemud_client_stream *stream;

    /* XXX sub-optimal - we really should be taking the server lock
     * first, but we have no handle to the server object
     * We're lucky to get away with it for now, due to this callback
     * executing in the main thread, but this should really be fixed
     */
    virMutexLock(&client->lock);

    stream = remoteFindClientStream(client, st);

    if (!stream) {
        VIR_WARN("event for client=%p stream st=%p, but missing stream state", client, st);
        virStreamEventRemoveCallback(st);
        goto cleanup;
    }

    VIR_DEBUG("st=%p events=%d", st, events);

    if (events & VIR_STREAM_EVENT_WRITABLE) {
        if (remoteStreamHandleWrite(client, stream) < 0) {
            remoteRemoveClientStream(client, stream);
            qemudDispatchClientFailure(client);
            goto cleanup;
        }
    }

    if (!stream->recvEOF &&
        (events & (VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP))) {
        events = events & ~(VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP);
        if (remoteStreamHandleRead(client, stream) < 0) {
            remoteRemoveClientStream(client, stream);
            qemudDispatchClientFailure(client);
            goto cleanup;
        }
    }

    if (!stream->closed &&
        (events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) {
        int ret;
        remote_error rerr;
        memset(&rerr, 0, sizeof rerr);
        stream->closed = 1;
        virStreamEventRemoveCallback(stream->st);
        virStreamAbort(stream->st);
        if (events & VIR_STREAM_EVENT_HANGUP)
            remoteDispatchFormatError(&rerr, "%s", _("stream had unexpected termination"));
        else
            remoteDispatchFormatError(&rerr, "%s", _("stream had I/O failure"));
        ret = remoteSerializeStreamError(client, &rerr, stream->procedure, stream->serial);
        remoteRemoveClientStream(client, stream);
        if (ret < 0)
            qemudDispatchClientFailure(client);
        goto cleanup;
    }

    if (stream->closed) {
        remoteRemoveClientStream(client, stream);
    } else {
        remoteStreamUpdateEvents(stream);
    }

cleanup:
    virMutexUnlock(&client->lock);
}
Exemplo n.º 11
0
static bool
cmdVolDownload(vshControl *ctl, const vshCmd *cmd)
{
    const char *file = NULL;
    virStorageVolPtr vol = NULL;
    bool ret = false;
    int fd = -1;
    virStreamPtr st = NULL;
    const char *name = NULL;
    unsigned long long offset = 0, length = 0;
    bool created = false;

    if (!vshConnectionUsability(ctl, ctl->conn))
        return false;

    if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
        vshError(ctl, _("Unable to parse integer"));
        return false;
    }

    if (vshCommandOptULongLong(cmd, "length", &length) < 0) {
        vshError(ctl, _("Unable to parse integer"));
        return false;
    }

    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name)))
        return false;

    if (vshCommandOptString(cmd, "file", &file) < 0) {
        vshError(ctl, _("file must not be empty"));
        goto cleanup;
    }

    if ((fd = open(file, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) {
        if (errno != EEXIST ||
            (fd = open(file, O_WRONLY|O_TRUNC, 0666)) < 0) {
            vshError(ctl, _("cannot create %s"), file);
            goto cleanup;
        }
    } else {
        created = true;
    }

    st = virStreamNew(ctl->conn, 0);
    if (virStorageVolDownload(vol, st, offset, length, 0) < 0) {
        vshError(ctl, _("cannot download from volume %s"), name);
        goto cleanup;
    }

    if (virStreamRecvAll(st, vshStreamSink, &fd) < 0) {
        vshError(ctl, _("cannot receive data from volume %s"), name);
        goto cleanup;
    }

    if (VIR_CLOSE(fd) < 0) {
        vshError(ctl, _("cannot close file %s"), file);
        virStreamAbort(st);
        goto cleanup;
    }

    if (virStreamFinish(st) < 0) {
        vshError(ctl, _("cannot close volume %s"), name);
        goto cleanup;
    }

    ret = true;

cleanup:
    VIR_FORCE_CLOSE(fd);
    if (!ret && created)
        unlink(file);
    if (vol)
        virStorageVolFree(vol);
    if (st)
        virStreamFree(st);
    return ret;
}
Exemplo n.º 12
0
static bool
cmdVolUpload(vshControl *ctl, const vshCmd *cmd)
{
    const char *file = NULL;
    virStorageVolPtr vol = NULL;
    bool ret = false;
    int fd = -1;
    virStreamPtr st = NULL;
    const char *name = NULL;
    unsigned long long offset = 0, length = 0;

    if (!vshConnectionUsability(ctl, ctl->conn))
        goto cleanup;

    if (vshCommandOptULongLong(cmd, "offset", &offset) < 0) {
        vshError(ctl, _("Unable to parse integer"));
        return false;
    }

    if (vshCommandOptULongLong(cmd, "length", &length) < 0) {
        vshError(ctl, _("Unable to parse integer"));
        return false;
    }

    if (!(vol = vshCommandOptVol(ctl, cmd, "vol", "pool", &name))) {
        return false;
    }

    if (vshCommandOptString(cmd, "file", &file) < 0) {
        vshError(ctl, _("file must not be empty"));
        goto cleanup;
    }

    if ((fd = open(file, O_RDONLY)) < 0) {
        vshError(ctl, _("cannot read %s"), file);
        goto cleanup;
    }

    st = virStreamNew(ctl->conn, 0);
    if (virStorageVolUpload(vol, st, offset, length, 0) < 0) {
        vshError(ctl, _("cannot upload to volume %s"), name);
        goto cleanup;
    }

    if (virStreamSendAll(st, cmdVolUploadSource, &fd) < 0) {
        vshError(ctl, _("cannot send data to volume %s"), name);
        goto cleanup;
    }

    if (VIR_CLOSE(fd) < 0) {
        vshError(ctl, _("cannot close file %s"), file);
        virStreamAbort(st);
        goto cleanup;
    }

    if (virStreamFinish(st) < 0) {
        vshError(ctl, _("cannot close volume %s"), name);
        goto cleanup;
    }

    ret = true;

cleanup:
    if (vol)
        virStorageVolFree(vol);
    if (st)
        virStreamFree(st);
    VIR_FORCE_CLOSE(fd);
    return ret;
}