c@90: c@90: #ifndef PIPER_PIPED_QPROCESS_TRANSPORT_H c@90: #define PIPER_PIPED_QPROCESS_TRANSPORT_H c@90: c@90: #include "SynchronousTransport.h" c@90: c@90: #include c@90: #include c@90: c@90: #include c@90: c@90: namespace piper { //!!! change c@90: c@90: class PipedQProcessTransport : public SynchronousTransport c@90: { c@90: public: c@90: PipedQProcessTransport(QString processName, c@90: MessageCompletenessChecker *checker) : //!!! ownership c@90: m_completenessChecker(checker) { c@90: m_process = new QProcess(); c@90: m_process->setReadChannel(QProcess::StandardOutput); c@90: m_process->setProcessChannelMode(QProcess::ForwardedErrorChannel); c@90: m_process->start(processName); c@90: if (!m_process->waitForStarted()) { c@90: std::cerr << "server failed to start" << std::endl; c@90: delete m_process; c@90: m_process = nullptr; c@90: } c@90: } c@90: c@90: ~PipedQProcessTransport() { c@90: if (m_process) { c@90: if (m_process->state() != QProcess::NotRunning) { c@90: m_process->closeWriteChannel(); c@90: m_process->waitForFinished(200); c@90: m_process->close(); c@90: m_process->waitForFinished(); c@90: std::cerr << "server exited" << std::endl; c@90: } c@90: delete m_process; c@90: } c@90: } c@90: c@90: bool isOK() const override { c@90: return m_process != nullptr; c@90: } c@90: c@90: std::vector c@90: call(const char *ptr, size_t size) override { c@90: c@90: m_process->write(ptr, size); c@90: c@90: std::vector buffer; c@90: size_t wordSize = sizeof(capnp::word); c@90: bool complete = false; c@90: c@90: while (!complete) { c@90: c@90: m_process->waitForReadyRead(1000); c@90: qint64 byteCount = m_process->bytesAvailable(); c@90: qint64 wordCount = byteCount / wordSize; c@90: c@90: if (!wordCount) { c@90: if (m_process->state() == QProcess::NotRunning) { c@90: std::cerr << "ERROR: Subprocess exited: Load failed" << std::endl; c@90: throw std::runtime_error("Piper server exited unexpectedly"); c@90: } c@90: } else { c@90: // only read whole words c@90: byteCount = wordCount * wordSize; c@90: size_t formerSize = buffer.size(); c@90: buffer.resize(formerSize + byteCount); c@90: m_process->read(buffer.data() + formerSize, byteCount); c@90: complete = m_completenessChecker->isComplete(buffer); c@90: } c@90: } c@90: /* c@90: cerr << "buffer = "; c@90: for (int i = 0; i < buffer.size(); ++i) { c@90: if (i % 16 == 0) cerr << "\n"; c@90: cerr << int(buffer[i]) << " "; c@90: } c@90: cerr << "\n"; c@90: */ c@90: return buffer; c@90: } c@90: c@90: private: c@90: MessageCompletenessChecker *m_completenessChecker; //!!! I don't own this (currently) c@90: QProcess *m_process; // I own this c@90: }; c@90: c@90: } c@90: c@90: #endif