c@90
|
1
|
c@90
|
2 #ifndef PIPER_PIPED_QPROCESS_TRANSPORT_H
|
c@90
|
3 #define PIPER_PIPED_QPROCESS_TRANSPORT_H
|
c@90
|
4
|
c@90
|
5 #include "SynchronousTransport.h"
|
c@90
|
6
|
c@90
|
7 #include <QProcess>
|
c@90
|
8 #include <QString>
|
c@90
|
9
|
c@90
|
10 #include <iostream>
|
c@90
|
11
|
c@90
|
12 namespace piper { //!!! change
|
c@90
|
13
|
c@90
|
14 class PipedQProcessTransport : public SynchronousTransport
|
c@90
|
15 {
|
c@90
|
16 public:
|
c@90
|
17 PipedQProcessTransport(QString processName,
|
c@90
|
18 MessageCompletenessChecker *checker) : //!!! ownership
|
c@90
|
19 m_completenessChecker(checker) {
|
c@90
|
20 m_process = new QProcess();
|
c@90
|
21 m_process->setReadChannel(QProcess::StandardOutput);
|
c@90
|
22 m_process->setProcessChannelMode(QProcess::ForwardedErrorChannel);
|
c@90
|
23 m_process->start(processName);
|
c@90
|
24 if (!m_process->waitForStarted()) {
|
c@90
|
25 std::cerr << "server failed to start" << std::endl;
|
c@90
|
26 delete m_process;
|
c@90
|
27 m_process = nullptr;
|
c@90
|
28 }
|
c@90
|
29 }
|
c@90
|
30
|
c@90
|
31 ~PipedQProcessTransport() {
|
c@90
|
32 if (m_process) {
|
c@90
|
33 if (m_process->state() != QProcess::NotRunning) {
|
c@90
|
34 m_process->closeWriteChannel();
|
c@90
|
35 m_process->waitForFinished(200);
|
c@90
|
36 m_process->close();
|
c@90
|
37 m_process->waitForFinished();
|
c@90
|
38 std::cerr << "server exited" << std::endl;
|
c@90
|
39 }
|
c@90
|
40 delete m_process;
|
c@90
|
41 }
|
c@90
|
42 }
|
c@90
|
43
|
c@90
|
44 bool isOK() const override {
|
c@90
|
45 return m_process != nullptr;
|
c@90
|
46 }
|
c@90
|
47
|
c@90
|
48 std::vector<char>
|
c@90
|
49 call(const char *ptr, size_t size) override {
|
c@90
|
50
|
c@90
|
51 m_process->write(ptr, size);
|
c@90
|
52
|
c@90
|
53 std::vector<char> buffer;
|
c@90
|
54 size_t wordSize = sizeof(capnp::word);
|
c@90
|
55 bool complete = false;
|
c@90
|
56
|
c@90
|
57 while (!complete) {
|
c@90
|
58
|
c@90
|
59 m_process->waitForReadyRead(1000);
|
c@90
|
60 qint64 byteCount = m_process->bytesAvailable();
|
c@90
|
61 qint64 wordCount = byteCount / wordSize;
|
c@90
|
62
|
c@90
|
63 if (!wordCount) {
|
c@90
|
64 if (m_process->state() == QProcess::NotRunning) {
|
c@90
|
65 std::cerr << "ERROR: Subprocess exited: Load failed" << std::endl;
|
c@90
|
66 throw std::runtime_error("Piper server exited unexpectedly");
|
c@90
|
67 }
|
c@90
|
68 } else {
|
c@90
|
69 // only read whole words
|
c@90
|
70 byteCount = wordCount * wordSize;
|
c@90
|
71 size_t formerSize = buffer.size();
|
c@90
|
72 buffer.resize(formerSize + byteCount);
|
c@90
|
73 m_process->read(buffer.data() + formerSize, byteCount);
|
c@90
|
74 complete = m_completenessChecker->isComplete(buffer);
|
c@90
|
75 }
|
c@90
|
76 }
|
c@90
|
77 /*
|
c@90
|
78 cerr << "buffer = ";
|
c@90
|
79 for (int i = 0; i < buffer.size(); ++i) {
|
c@90
|
80 if (i % 16 == 0) cerr << "\n";
|
c@90
|
81 cerr << int(buffer[i]) << " ";
|
c@90
|
82 }
|
c@90
|
83 cerr << "\n";
|
c@90
|
84 */
|
c@90
|
85 return buffer;
|
c@90
|
86 }
|
c@90
|
87
|
c@90
|
88 private:
|
c@90
|
89 MessageCompletenessChecker *m_completenessChecker; //!!! I don't own this (currently)
|
c@90
|
90 QProcess *m_process; // I own this
|
c@90
|
91 };
|
c@90
|
92
|
c@90
|
93 }
|
c@90
|
94
|
c@90
|
95 #endif
|