/* * 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; }
/* * 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; }
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); } }
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; }