GCC Code Coverage Report


Directory: ./
File: qtpdcom/QtPdCom1/Process.h
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 0 4 0.0%
Branches: 0 2 0.0%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2009-2022 Florian Pose <fp@igh.de>
4 *
5 * This file is part of the QtPdCom library.
6 *
7 * The QtPdCom library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * The QtPdCom library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the QtPdCom Library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22 #ifndef QTPDCOM_PROCESS_H
23 #define QTPDCOM_PROCESS_H
24
25 #include <QObject>
26 #include <QString>
27 #include <QList>
28 #include <QSslCertificate>
29 #include <QUrl>
30
31 #include <pdcom5.h>
32 #include <pdcom5/ClientStatistics.h>
33 #include <pdcom5/Process.h>
34 #include <QFuture>
35
36 #ifndef PDCOM_VERSION_CODE
37 # error "No PDCOM_VERSION_CODE found."
38 #elif \
39 !PDCOM_DEVEL \
40 && (PDCOM_VERSION_CODE < PDCOM_VERSION(5, 0, 0) \
41 || PDCOM_VERSION_CODE >= PDCOM_VERSION(6, 0, 0))
42 # error "Invalid PdCom version."
43 #endif
44
45 #include "Export.h"
46 #include "FutureWatchers.h"
47 #include "VariableList.h"
48
49 class QTranslator;
50 class QSslKey;
51
52 namespace QtPdCom {
53
54 class LoginManager;
55
56 /****************************************************************************/
57
58 /** PdCom::Process implementation for Qt.
59 */
60 class QTPDCOM_PUBLIC Process:
61 public QObject, public PdCom::Process
62 {
63 Q_OBJECT
64 Q_PROPERTY(bool connected READ isConnected NOTIFY connectionStatusChanged)
65 Q_PROPERTY(ConnectionState connectionState READ getConnectionState NOTIFY connectionStatusChanged)
66 Q_PROPERTY(SslCaMode sslCaMode READ getCaMode WRITE setCaMode NOTIFY sslCaModeChanged)
67 Q_PROPERTY(int port READ getPort NOTIFY connectionStatusChanged)
68 Q_PROPERTY(QString host READ getHost NOTIFY connectionStatusChanged)
69 Q_PROPERTY(QUrl url READ getUrl NOTIFY connectionStatusChanged)
70 Q_PROPERTY(QString applicationName READ getApplicationName WRITE setApplicationName)
71 Q_PROPERTY(QtPdCom::LoginManager * loginManager READ getLoginManager WRITE setLoginManager)
72
73 public:
74 enum class SslCaMode {
75 NoTLS, /**< Disable TLS, unencrypted traffic only. */
76 DefaultCAs /**< Use system-default Certificate Authories. */,
77 CustomCAs /**< Use provided CAs only. */,
78 IgnoreCertificate /**< Accept any server certificate. */,
79 };
80 Q_ENUM(SslCaMode)
81
82 Process(QObject *parent = nullptr);
83 virtual ~Process();
84
85 void setApplicationName(const QString &);
86 QString getApplicationName() const;
87 Q_INVOKABLE void connectToHost(const QString &, quint16 = 2345);
88 Q_INVOKABLE void disconnectFromHost();
89
90 /** State of the process connection.
91 */
92 enum ConnectionState {
93 Disconnected, /**< Process disconnected. */
94 Connecting, /**< Currently connecting. */
95 Connected, /**< Process connection established. */
96 ConnectError, /**< An error happened while connecting. */
97 ConnectedError /**< An error happened, after the connection was
98 established. */
99 };
100 Q_ENUM(ConnectionState);
101
102 ConnectionState getConnectionState() const;
103 bool isConnected() const;
104 const QString &getErrorString() const;
105 QString getPeerName() const;
106 QUrl getUrl() const;
107 int getPort() const;
108 QString getHost() const;
109
110 Q_INVOKABLE void sendBroadcast(const QString &, const QString &attr = "text");
111 quint64 getRxBytes() const;
112 quint64 getTxBytes() const;
113
114 /** Find a Variable.
115 *
116 * Finding a variable is asynchronous in general. If you need to write
117 * to a variable, a variable object is needed. To write a variable
118 * with a single call you can use futures and a lambda function. See
119 * the example in the overloaded method
120 * find(const QString&, Class *, Function&&).
121 *
122 * @return A Future. You can use VariableWatcher to monitor it.
123 */
124 QFuture<PdCom::Variable> find(const QString&);
125 QFuture<VariableList> list(const QString& = "");
126 QFuture<void> pingQt();
127 QFuture<std::vector<PdCom::ClientStatistics>> getClientStatisticsQt();
128
129 /** Also find a Variable.
130 *
131 * Here, a FutureWatcher is created on your behalf.
132 * Callback can be one of
133 * - a member Function of obj which takes a PdCom::Variable
134 * - a lambda which takes a reference to obj and a PdCom::Variable
135 * - a lambda which takes only a PdCom::Variable
136 *
137 * The obj reference is needed to use it as a parent for the watcher
138 * and to make the connections disconnect automatically when the Process
139 * or the object itself goes away.
140 *
141 * Below is an example of how to make use of a lambda function to find
142 * a variable and write to it once it is found:
143 *
144 * \code{.cpp}
145 * const double val = 30.0;
146 * const QString path = "/osc/amplitude/Setpoint";
147 *
148 * process->find(path, this, [val](const PdCom::Variable& var) {
149 * if (var.empty()) {
150 * std::cerr << "Variable not found." << std::endl;
151 * }
152 * else {
153 * var.setValue(val);
154 * std::cerr << "Set " << var.getPath()
155 * << " to " << val << std::endl;
156 * }
157 * });
158 * \endcode
159 *
160 * \param path Variable to find.
161 * \param obj QObject-derived class.
162 * \param callback Callback which receives the result.
163 * \return A freshly created FutureWatcher instance with all signals connected.
164 */
165 template<class Class, class Function>
166 QFutureWatcher<PdCom::Variable>& find(const QString& path, Class *obj, Function&& callback);
167 template<class Class, class Function>
168 QFutureWatcher<VariableList>& list(const QString& path, Class *obj, Function&& callback);
169 template<class Class, class Function>
170 QFutureWatcher<void>& ping(Class *obj, Function&& callback);
171 template<class Class, class Function>
172 QFutureWatcher<std::vector<PdCom::ClientStatistics>>&
173 getClientStatistics(Class *obj, Function&& callback);
174
175 /**
176 * Set Traffic Encryption mode.
177 *
178 * See the SslCaMode enum for details.
179 *
180 * \param mode Mode.
181 */
182 void setCaMode(SslCaMode mode);
183 /**
184 * Get Traffic Encryption mode.
185 *
186 * \return Traffic Encryption mode.
187 */
188 SslCaMode getCaMode() const;
189
190 /**
191 * Provide a client certificate.
192 *
193 * \param cert Public certificate.
194 * \param key Private key.
195 */
196 void setClientCertificate(const QSslCertificate& cert,const QSslKey& key);
197 /**
198 * Set list of trusted Certificate Authorities.
199 *
200 * For \c SslCaMode::CustomCAs mode.
201 *
202 * \param cas List of trusted CAs.
203 */
204 void setCustomCAs(QList<QSslCertificate> cas);
205
206 static QtPdCom::Process *getDefaultProcess();
207 static void setDefaultProcess(QtPdCom::Process *);
208
209 PdCom::MessageManagerBase *getMessageManager() const;
210
211 /**
212 * Set the Login Manager.
213 * \param lm The Login manager. May be \c NULL.
214 */
215 void setLoginManager(LoginManager* lm);
216 LoginManager *getLoginManager() const;
217 private:
218 struct Q_DECL_HIDDEN Impl;
219 std::unique_ptr<Impl> impl;
220
221 /** Virtual from PdCom::Process. */
222 std::string applicationName() const override;
223 std::string hostname() const override;
224 int read(char *, int) override;
225 void write(const char *, size_t) override;
226 void flush() override;
227 void connected() override;
228 void broadcastReply(
229 const std::string &message,
230 const std::string &attr,
231 std::chrono::nanoseconds time_ns,
232 const std::string &user) override;
233 void pingReply() override;
234 void findReply(PdCom::Variable const& var) override;
235 void listReply(std::vector<PdCom::Variable> vars, std::vector<std::string> dirs) override;
236 void clientStatisticsReply(std::vector<PdCom::ClientStatistics> statistics) override;
237 void reset();
238
239 /** Disconnect method inherited from QObject.
240 *
241 * This is made private, to avoid confusion.
242 */
243 bool disconnect(
244 const char *signal = 0, /**< Signal. */
245 const QObject *receiver = 0, /**< Receiver. */
246 const char *method = 0 /**< Method. */
247 );
248
249 // make setMessageManager() private
250 using PdCom::Process::setMessageManager;
251
252 signals:
253 /** Connection established.
254 *
255 * This is emitted after the connection is established.
256 */
257 void processConnected();
258
259 /** Disconnected gracefully.
260 *
261 * This is only emitted, after the user called disconnectFromHost().
262 */
263 void disconnected();
264
265 /** Connection error.
266 *
267 * This is emitted after a connection error or when the connection was
268 * closed due to a parser error.
269 */
270 void error();
271
272 void broadcastReceived(
273 const QString &message,
274 const QString &attr,
275 std::uint64_t time_ns,
276 const QString &user);
277
278 void connectionStatusChanged();
279
280 void sslCaModeChanged();
281
282
283 private slots:
284 void socketConnected();
285 void socketDisconnected();
286 void socketError();
287 void socketRead();
288 };
289
290 /****************************************************************************/
291
292 template<class Class, class Function>
293 inline QFutureWatcher<PdCom::Variable>& Process::find(
294 const QString& path, Class *obj, Function&& callback)
295 {
296 auto& ans = createWatcher<PdCom::Variable>(obj, callback);
297 ans.setFuture(find(path));
298 return ans;
299 }
300
301 /****************************************************************************/
302
303 template<class Class, class Function>
304 inline QFutureWatcher<VariableList>& Process::list(const QString& path, Class *obj, Function&& callback)
305 {
306 auto& ans = createWatcher<VariableList>(obj, callback);
307 ans.setFuture(list(path));
308 return ans;
309 }
310
311 /****************************************************************************/
312
313 template<class Class, class Function>
314 inline QFutureWatcher<void>& Process::ping(Class *obj, Function&& callback)
315 {
316 auto& ans = createWatcher<void>(obj, callback);
317 ans.setFuture(pingQt());
318 return ans;
319 }
320
321 /****************************************************************************/
322
323 template<class Class, class Function>
324 inline QFutureWatcher<std::vector<PdCom::ClientStatistics>>&
325 Process::getClientStatistics(Class *obj, Function&& callback)
326 {
327 auto& ans = createWatcher<std::vector<PdCom::ClientStatistics>>(
328 obj, callback
329 );
330 ans.setFuture(getClientStatisticsQt());
331 return ans;
332 }
333
334 /****************************************************************************/
335
336 } // namespace
337
338 #endif
339